From 0cf61b105df802e2e58134ebaa670277bab5894b Mon Sep 17 00:00:00 2001 From: shogo4405 Date: Sat, 14 Oct 2023 16:11:41 +0900 Subject: [PATCH] Bump to libsrt up v1.5.3 --- .gitignore | 1 + README.md | 4 +- Vendor/SRT/build-xcframework.sh | 17 +- .../ios-arm64/Headers/access_control.h | 2 +- .../ios-arm64/Headers/api.h | 11 + .../ios-arm64/Headers/buffer.h | 611 --------- .../ios-arm64/Headers/buffer_rcv.h | 73 +- .../ios-arm64/Headers/buffer_snd.h | 259 ++++ .../ios-arm64/Headers/buffer_tools.h | 201 +++ .../ios-arm64/Headers/cache.h | 2 +- .../ios-arm64/Headers/channel.h | 133 +- .../ios-arm64/Headers/common.h | 16 +- .../ios-arm64/Headers/congctl.h | 4 +- .../ios-arm64/Headers/core.h | 155 ++- .../ios-arm64/Headers/crypto.h | 33 +- .../ios-arm64/Headers/epoll.h | 5 +- .../ios-arm64/Headers/fec.h | 6 +- .../ios-arm64/Headers/group.h | 37 +- .../ios-arm64/Headers/list.h | 22 +- .../ios-arm64/Headers/logging.h | 29 +- .../ios-arm64/Headers/md5.h | 32 +- .../ios-arm64/Headers/netinet_any.h | 426 +++++++ .../ios-arm64/Headers/packet.h | 397 ++++++ .../ios-arm64/Headers/packetfilter.h | 219 ++++ .../ios-arm64/Headers/packetfilter_api.h | 158 +++ .../ios-arm64/Headers/packetfilter_builtin.h | 18 + .../ios-arm64/Headers/platform_sys.h | 97 +- .../ios-arm64/Headers/queue.h | 603 +++++++++ .../ios-arm64/Headers/socketconfig.h | 410 ++++++ .../ios-arm64/Headers/srt.h | 634 +++++++--- .../ios-arm64/Headers/srt4udt.h | 71 -- .../ios-arm64/Headers/srt_attr_defs.h | 191 +++ .../ios-arm64/Headers/srt_compat.h | 109 ++ .../ios-arm64/Headers/stats.h | 221 ++++ .../ios-arm64/Headers/sync.h | 947 ++++++++++++++ .../ios-arm64/Headers/threadname.h | 224 ++++ .../ios-arm64/Headers/tsbpd_time.h | 163 +++ .../ios-arm64/Headers/udt.h | 345 ++---- .../ios-arm64/Headers/utilities.h | 1098 +++++++++++++++++ .../ios-arm64/Headers/version.h | 4 +- .../ios-arm64/Headers/window.h | 355 ++++++ .../SRT/libsrt.xcframework/ios-arm64/libsrt.a | Bin 8737256 -> 8737256 bytes .../Headers/access_control.h | 2 +- .../ios-arm64_x86_64-simulator/Headers/api.h | 11 + .../Headers/buffer.h | 611 --------- .../Headers/buffer_rcv.h | 73 +- .../Headers/buffer_snd.h | 259 ++++ .../Headers/buffer_tools.h | 201 +++ .../Headers/cache.h | 2 +- .../Headers/channel.h | 133 +- .../Headers/common.h | 16 +- .../Headers/congctl.h | 4 +- .../ios-arm64_x86_64-simulator/Headers/core.h | 155 ++- .../Headers/crypto.h | 33 +- .../Headers/epoll.h | 5 +- .../ios-arm64_x86_64-simulator/Headers/fec.h | 6 +- .../Headers/group.h | 37 +- .../ios-arm64_x86_64-simulator/Headers/list.h | 22 +- .../Headers/logging.h | 29 +- .../ios-arm64_x86_64-simulator/Headers/md5.h | 32 +- .../Headers/netinet_any.h | 426 +++++++ .../Headers/packet.h | 397 ++++++ .../Headers/packetfilter.h | 219 ++++ .../Headers/packetfilter_api.h | 158 +++ .../Headers/packetfilter_builtin.h | 18 + .../Headers/platform_sys.h | 97 +- .../Headers/queue.h | 603 +++++++++ .../Headers/socketconfig.h | 410 ++++++ .../ios-arm64_x86_64-simulator/Headers/srt.h | 634 +++++++--- .../Headers/srt4udt.h | 71 -- .../Headers/srt_attr_defs.h | 191 +++ .../Headers/srt_compat.h | 109 ++ .../Headers/stats.h | 221 ++++ .../ios-arm64_x86_64-simulator/Headers/sync.h | 947 ++++++++++++++ .../Headers/threadname.h | 224 ++++ .../Headers/tsbpd_time.h | 163 +++ .../ios-arm64_x86_64-simulator/Headers/udt.h | 345 ++---- .../Headers/utilities.h | 1098 +++++++++++++++++ .../Headers/version.h | 4 +- .../Headers/window.h | 355 ++++++ .../ios-arm64_x86_64-simulator/libsrt.a | Bin 17345856 -> 17345856 bytes .../Headers/access_control.h | 2 +- .../macos-arm64_x86_64/Headers/api.h | 11 + .../macos-arm64_x86_64/Headers/buffer.h | 611 --------- .../macos-arm64_x86_64/Headers/buffer_rcv.h | 73 +- .../macos-arm64_x86_64/Headers/buffer_snd.h | 259 ++++ .../macos-arm64_x86_64/Headers/buffer_tools.h | 201 +++ .../macos-arm64_x86_64/Headers/cache.h | 2 +- .../macos-arm64_x86_64/Headers/channel.h | 133 +- .../macos-arm64_x86_64/Headers/common.h | 16 +- .../macos-arm64_x86_64/Headers/congctl.h | 4 +- .../macos-arm64_x86_64/Headers/core.h | 155 ++- .../macos-arm64_x86_64/Headers/crypto.h | 33 +- .../macos-arm64_x86_64/Headers/epoll.h | 5 +- .../macos-arm64_x86_64/Headers/fec.h | 6 +- .../macos-arm64_x86_64/Headers/group.h | 37 +- .../macos-arm64_x86_64/Headers/list.h | 22 +- .../macos-arm64_x86_64/Headers/logging.h | 29 +- .../macos-arm64_x86_64/Headers/md5.h | 32 +- .../macos-arm64_x86_64/Headers/netinet_any.h | 426 +++++++ .../macos-arm64_x86_64/Headers/packet.h | 397 ++++++ .../macos-arm64_x86_64/Headers/packetfilter.h | 219 ++++ .../Headers/packetfilter_api.h | 158 +++ .../Headers/packetfilter_builtin.h | 18 + .../macos-arm64_x86_64/Headers/platform_sys.h | 97 +- .../macos-arm64_x86_64/Headers/queue.h | 603 +++++++++ .../macos-arm64_x86_64/Headers/socketconfig.h | 410 ++++++ .../macos-arm64_x86_64/Headers/srt.h | 634 +++++++--- .../macos-arm64_x86_64/Headers/srt4udt.h | 71 -- .../Headers/srt_attr_defs.h | 191 +++ .../macos-arm64_x86_64/Headers/srt_compat.h | 109 ++ .../macos-arm64_x86_64/Headers/stats.h | 221 ++++ .../macos-arm64_x86_64/Headers/sync.h | 947 ++++++++++++++ .../macos-arm64_x86_64/Headers/threadname.h | 224 ++++ .../macos-arm64_x86_64/Headers/tsbpd_time.h | 163 +++ .../macos-arm64_x86_64/Headers/udt.h | 345 ++---- .../macos-arm64_x86_64/Headers/utilities.h | 1098 +++++++++++++++++ .../macos-arm64_x86_64/Headers/version.h | 4 +- .../macos-arm64_x86_64/Headers/window.h | 355 ++++++ .../macos-arm64_x86_64/libsrt.a | Bin 15642360 -> 15642360 bytes Vendor/SRT/module.modulemap | 4 + 121 files changed, 21146 insertions(+), 3843 deletions(-) delete mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_snd.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_tools.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/netinet_any.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packet.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_api.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_builtin.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/queue.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/socketconfig.h delete mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt4udt.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_attr_defs.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_compat.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/stats.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/sync.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/threadname.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/tsbpd_time.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/utilities.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/window.h delete mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_snd.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_tools.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/netinet_any.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packet.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_api.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_builtin.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/queue.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/socketconfig.h delete mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt4udt.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_attr_defs.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_compat.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/stats.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/sync.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/threadname.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/tsbpd_time.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/utilities.h create mode 100644 Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/window.h delete mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_snd.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_tools.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/netinet_any.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packet.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_api.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_builtin.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/queue.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/socketconfig.h delete mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt4udt.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_attr_defs.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_compat.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/stats.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/sync.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/threadname.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/tsbpd_time.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/utilities.h create mode 100644 Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/window.h create mode 100644 Vendor/SRT/module.modulemap diff --git a/.gitignore b/.gitignore index 8b4fce9e4..d66b8c96c 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,6 @@ fastlane/report.xml docs/docsets/HaishinKit.docset/Contents/Resources/Documents/undocumented.json Vendor/SRT/OpenSSL/ Vendor/SRT/srt/ +Vendor/SRT/Includes/ HaishinKit.json SRTHaishinKit.json diff --git a/README.md b/README.md index 7f8924ee6..34e1508ed 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Swift Compatibility](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fshogo4405%2FHaishinKit.swift%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/shogo4405/HaishinKit.swift) [![GitHub license](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://raw.githubusercontent.com/shogo4405/HaishinKit.swift/master/LICENSE.md) -* Camera and Microphone streaming library via RTMP, HLS and SRT for iOS, macOS, tvOS. +* Camera and Microphone streaming library via RTMP and SRT for iOS, macOS, tvOS. * README.md contains unreleased content, which can be tested on the main branch. * [API Documentation](https://shogo4405.github.io/HaishinKit.swift/documentation/haishinkit) @@ -122,7 +122,7 @@ open HaishinKit.xcodeproj |-|iOS|tvOS|macOS|visionOS|watchOS| |:----|:----:|:----:|:----:|:----:|:----:| |HaishinKit|12.0+|12.0+|10.13+|-|-| -|SRTHaishinKit|12.0+|-|-|-|-| +|SRTHaishinKit|12.0+|-|13.0+|-|-| ### Cocoa Keys Please contains Info.plist. diff --git a/Vendor/SRT/build-xcframework.sh b/Vendor/SRT/build-xcframework.sh index 114595937..b51f9ca3c 100755 --- a/Vendor/SRT/build-xcframework.sh +++ b/Vendor/SRT/build-xcframework.sh @@ -15,6 +15,8 @@ else popd fi +rm -rf Includes +mkdir Includes cp srt/srtcore/*.h Includes srt() { @@ -39,25 +41,20 @@ srt_macosx() { # macOS srt_macosx macosx arm64 -rm -f ./build/macosx/libsrt-lipo.a -libtool -static -o ./build/macosx/libsrt.a ./build/macosx/arm64/libsrt.a ./OpenSSL/macosx/lib/libcrypto.a ./OpenSSL/macosx/lib/libssl.a +libtool -static -o ./build/macosx/libsrt.a ./build/macosx/arm64/libsrt.a ./OpenSSL/macosx/lib/libcrypto.a ./OpenSSL/macosx/lib/libssl.a # iOS export IPHONEOS_DEPLOYMENT_TARGET=12.0 SDKVERSION=$(xcrun --sdk iphoneos --show-sdk-version) -srt iphonesimulator SIMULATOR64 x86_64 srt iphonesimulator SIMULATOR64 arm64 srt iphoneos OS arm64 - -rm -f ./build/SIMULATOR64/libsrt-lipo.a -lipo -create ./build/SIMULATOR64/arm64/libsrt.a ./build/SIMULATOR64/x86_64/libsrt.a -output ./build/SIMULATOR64/libsrt-lipo.a -libtool -static -o ./build/SIMULATOR64/libsrt.a ./build/SIMULATOR64/libsrt-lipo.a ./OpenSSL/iphonesimulator/lib/libcrypto.a ./OpenSSL/iphonesimulator/lib/libssl.a - -rm -f ./build/OS/libsrt-lipo.a -lipo -create ./build/OS/arm64/libsrt.a -output ./build/OS/libsrt-lipo.a +libtool -static -o ./build/SIMULATOR64/arm64/libsrt.a ./OpenSSL/iphonesimulator/lib/libcrypto.a ./OpenSSL/iphonesimulator/lib/libssl.a libtool -static -o ./build/OS/libsrt.a ./build/OS/libsrt-lipo.a ./OpenSSL/iphoneos/lib/libcrypto.a ./OpenSSL/iphoneos/lib/libssl.a # make libsrt.xcframework +cp module.modulemap Includes/module.modulemap +cp ./build/OS/arm64/version.h Includes/version.h + rm -rf libsrt.xcframework xcodebuild -create-xcframework \ -library ./build/SIMULATOR64/libsrt.a -headers Includes \ diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/access_control.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/access_control.h index 97a1104a8..611e1dad8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/access_control.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/access_control.h @@ -41,7 +41,7 @@ written by // CODE NOT IN USE 408: unused: no timeout predicted for listener callback #define SRT_REJX_CONFLICT 1409 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only. // CODE NOT IN USE 410: unused: treated as a specific case of 404 -// CODE NOT IN USE 411: unused: no reason to include lenght in the protocol +// CODE NOT IN USE 411: unused: no reason to include length in the protocol // CODE NOT IN USE 412: unused: preconditions not predicted in AC // CODE NOT IN USE 413: unused: AC size is already defined as 512 // CODE NOT IN USE 414: unused: AC size is already defined as 512 diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/api.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/api.h index ca812bf9e..9ba77d23a 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/api.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/api.h @@ -193,6 +193,15 @@ class CUDTSocket /// to finish sending the data that were scheduled for sending so far. void setClosed(); + // This is necessary to be called from the group before the group clears + // the connection with the socket. As for managed groups (and there are + // currently no other group types), a socket disconnected from the group + // is no longer usable. + void setClosing() + { + core().m_bClosing = true; + } + /// This does the same as setClosed, plus sets the m_bBroken to true. /// Such a socket can still be read from so that remaining data from /// the receiver buffer can be read, but no longer sends anything. @@ -447,6 +456,8 @@ class CUDTUnited /// @param cfgSocket socket configuration. /// @return tru if configurations match, false otherwise. static bool channelSettingsMatch(const CSrtMuxerConfig& cfgMuxer, const CSrtConfig& cfgSocket); + static bool inet6SettingsCompat(const sockaddr_any& muxaddr, const CSrtMuxerConfig& cfgMuxer, + const sockaddr_any& reqaddr, const CSrtMuxerConfig& cfgSocket); private: std::map m_mMultiplexer; // UDP multiplexer diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer.h deleted file mode 100644 index 48bcb4311..000000000 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer.h +++ /dev/null @@ -1,611 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2009 -modified by - Haivision Systems Inc. -*****************************************************************************/ - -#ifndef INC_SRT_BUFFER_H -#define INC_SRT_BUFFER_H - -#include "udt.h" -#include "list.h" -#include "queue.h" -#include "tsbpd_time.h" -#include "utilities.h" - -// The notation used for "circular numbers" in comments: -// The "cicrular numbers" are numbers that when increased up to the -// maximum become zero, and similarly, when the zero value is decreased, -// it turns into the maximum value minus one. This wrapping works the -// same for adding and subtracting. Circular numbers cannot be multiplied. - -// Operations done on these numbers are marked with additional % character: -// a %> b : a is later than b -// a ++% (++%a) : shift a by 1 forward -// a +% b : shift a by b -// a == b : equality is same as for just numbers - -namespace srt { - -/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) -class AvgBufSize -{ - typedef sync::steady_clock::time_point time_point; - -public: - AvgBufSize() - : m_dBytesCountMAvg(0.0) - , m_dCountMAvg(0.0) - , m_dTimespanMAvg(0.0) - { - } - -public: - bool isTimeToUpdate(const time_point& now) const; - void update(const time_point& now, int pkts, int bytes, int timespan_ms); - -public: - inline double pkts() const { return m_dCountMAvg; } - inline double timespan_ms() const { return m_dTimespanMAvg; } - inline double bytes() const { return m_dBytesCountMAvg; } - -private: - time_point m_tsLastSamplingTime; - double m_dBytesCountMAvg; - double m_dCountMAvg; - double m_dTimespanMAvg; -}; - -/// The class to estimate source bitrate based on samples submitted to the buffer. -/// Is currently only used by the CSndBuffer. -class CRateEstimator -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; -public: - CRateEstimator(); - -public: - uint64_t getInRatePeriod() const { return m_InRatePeriod; } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_iInRateBps; } - - void setInputRateSmpPeriod(int period); - - /// Update input rate calculation. - /// @param [in] time current time in microseconds - /// @param [in] pkts number of packets newly added to the buffer - /// @param [in] bytes number of payload bytes in those newly added packets - /// - /// @return Current size of the data in the sending list. - void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); - - void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } - -private: // Constants - static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms - static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms - static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload - static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; - -private: - int m_iInRatePktsCount; // number of payload bytes added since InRateStartTime - int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime - time_point m_tsInRateStartTime; - uint64_t m_InRatePeriod; // usec - int m_iInRateBps; // Input Rate in Bytes/sec -}; - -class CSndBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the buffer is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - /// @brief CSndBuffer constructor. - /// @param size initial number of blocks (each block to store one packet payload). - /// @param maxpld maximum packet payload. - CSndBuffer(int size = 32, int maxpld = 1500); - ~CSndBuffer(); - -public: - /// Insert a user buffer into the sending list. - /// For @a w_mctrl the following fields are used: - /// INPUT: - /// - msgttl: timeout for retransmitting the message, if lost - /// - inorder: request to deliver the message in order of sending - /// - srctime: local time as a base for packet's timestamp (0 if unused) - /// - pktseq: sequence number to be stamped on the packet (-1 if unused) - /// - msgno: message number to be stamped on the packet (-1 if unused) - /// OUTPUT: - /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) - /// - pktseq: sequence number to be stamped on the next packet - /// - msgno: message number stamped on the packet - /// @param [in] data pointer to the user data block. - /// @param [in] len size of the block. - /// @param [inout] w_mctrl Message control data - SRT_ATTR_EXCLUDES(m_BufLock) - void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); - - /// Read a block of data from file and insert it into the sending list. - /// @param [in] ifs input file stream. - /// @param [in] len size of the block. - /// @return actual size of data added from the file. - SRT_ATTR_EXCLUDES(m_BufLock) - int addBufferFromFile(std::fstream& ifs, int len); - - /// Find data position to pack a DATA packet from the furthest reading point. - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [in] kflags Odd|Even crypto key flag - /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. - /// @return Actual length of data read. - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); - - /// Peek an information on the next original data packet to send. - /// @return origin time stamp of the next packet; epoch start time otherwise. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point peekNextOriginal() const; - - /// Find data position to pack a DATA packet for a retransmission. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [out] msglen length of the message - /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); - - /// Get the time of the last retransmission (if any) of the DATA packet. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// - /// @return Last time of the last retransmission event for the corresponding DATA packet. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point getPacketRexmitTime(const int offset); - - /// Update the ACK point and may release/unmap/return the user data according to the flag. - /// @param [in] offset number of packets acknowledged. - int32_t getMsgNoAt(const int offset); - - void ackData(int offset); - - /// Read size of data still in the sending list. - /// @return Current size of the data in the sending list. - int getCurrBufSize() const; - - SRT_ATTR_EXCLUDES(m_BufLock) - int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); - - void updAvgBufSize(const time_point& time); - int getAvgBufSize(int& bytes, int& timespan); - int getCurrBufSize(int& bytes, int& timespan); - - /// @brief Get the buffering delay of the oldest message in the buffer. - /// @return the delay value. - SRT_ATTR_EXCLUDES(m_BufLock) - duration getBufferingDelay(const time_point& tnow) const; - - uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_rateEstimator.getInputRate(); } - - void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } - - const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } - - void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } - -private: - void increase(); - -private: - mutable sync::Mutex m_BufLock; // used to synchronize buffer operation - - struct Block - { - char* m_pcData; // pointer to the data block - int m_iLength; // payload length of the block. - - int32_t m_iMsgNoBitset; // message number - int32_t m_iSeqNo; // sequence number for scheduling - time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. - time_point m_tsRexmitTime; // packet retransmission time - int m_iTTL; // time to live (milliseconds) - - Block* m_pNext; // next block - - int32_t getMsgSeq() - { - // NOTE: this extracts message ID with regard to REXMIT flag. - // This is valid only for message ID that IS GENERATED in this instance, - // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter - // for the peer that it uses LESS bits to represent the message. - return m_iMsgNoBitset & MSGNO_SEQ::mask; - } - - } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; - - // m_pBlock: The head pointer - // m_pFirstBlock: The first block - // m_pCurrBlock: The current block - // m_pLastBlock: The last block (if first == last, buffer is empty) - - struct Buffer - { - char* m_pcData; // buffer - int m_iSize; // size - Buffer* m_pNext; // next buffer - } * m_pBuffer; // physical buffer - - int32_t m_iNextMsgNo; // next message number - - int m_iSize; // buffer size (number of packets) - const int m_iBlockLen; // maximum length of a block holding packet payload (excluding packet header). - int m_iCount; // number of used blocks - - int m_iBytesCount; // number of payload bytes in queue - time_point m_tsLastOriginTime; - - AvgBufSize m_mavg; - CRateEstimator m_rateEstimator; - -private: - CSndBuffer(const CSndBuffer&); - CSndBuffer& operator=(const CSndBuffer&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -#if (!ENABLE_NEW_RCVBUFFER) - -class CRcvBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the queue is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - static const int DEFAULT_SIZE = 65536; - /// Construct the buffer. - /// @param [in] queue CUnitQueue that actually holds the units (packets) - /// @param [in] bufsize_pkts in units (packets) - CRcvBuffer(CUnitQueue* queue, int bufsize_pkts = DEFAULT_SIZE); - ~CRcvBuffer(); - -public: - /// Write data into the buffer. - /// @param [in] unit pointer to a data unit containing new packet - /// @param [in] offset offset from last ACK point. - /// @return 0 is success, -1 if data is repeated. - int addData(CUnit* unit, int offset); - - /// Read data into a user buffer. - /// @param [in] data pointer to user buffer. - /// @param [in] len length of user buffer. - /// @return size of data read. - int readBuffer(char* data, int len); - - /// Read data directly into file. - /// @param [in] file C++ file stream. - /// @param [in] len expected length of data to write into the file. - /// @return size of data read. - int readBufferToFile(std::fstream& ofs, int len); - - /// Update the ACK point of the buffer. - /// @param [in] len number of units to be acknowledged. - /// @return 1 if a user buffer is fulfilled, otherwise 0. - int ackData(int len); - - /// Query how many buffer space left for data receiving. - /// Actually only acknowledged packets, that are still in the buffer, - /// are considered to take buffer space. - /// - /// @return size of available buffer space (including user buffer) for data receiving. - /// Not counting unacknowledged packets. - int getAvailBufSize() const; - - /// Query how many data has been continuously received (for reading) and ready to play (tsbpdtime < now). - /// @return size of valid (continous) data for reading. - int getRcvDataSize() const; - - /// Query how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvDataSize(int& bytes, int& spantime); - - /// Query a 1 sec moving average of how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvAvgDataSize(int& bytes, int& spantime); - - /// Query how many data of the receive buffer is acknowledged. - /// @param [in] now current time in us. - /// @return none. - void updRcvAvgDataSize(const time_point& now); - - /// Query the received average payload size. - /// @return size (bytes) of payload size - unsigned getRcvAvgPayloadSize() const; - - struct ReadingState - { - time_point tsStart; - time_point tsLastAck; - time_point tsEnd; - int iNumAcknowledged; - int iNumUnacknowledged; - }; - - ReadingState debugGetReadingState() const; - - /// Form a string of the current buffer fullness state. - /// number of packets acknowledged, TSBPD readiness, etc. - std::string strFullnessState(const time_point& tsNow) const; - - /// Mark the message to be dropped from the message list. - /// @param [in] msgno message number. - /// @param [in] using_rexmit_flag whether the MSGNO field uses rexmit flag (if not, one more bit is part of the - /// msgno value) - void dropMsg(int32_t msgno, bool using_rexmit_flag); - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @return actuall size of data read. - int readMsg(char* data, int len); - -#if ENABLE_HEAVY_LOGGING - void readMsgHeavyLogging(int p); -#endif - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// @return actuall size of data read. - int readMsg(char* data, int len, SRT_MSGCTRL& w_mctrl, int upto); - - /// Query if data is ready to read (tsbpdtime <= now if TsbPD is active). - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// of next packet in recv buffer, ready or not. - /// @param [out] curpktseq Sequence number of the packet if there is one ready to play - /// @return true if ready to play, false otherwise (tsbpdtime may be !0 in - /// both cases). - bool isRcvDataReady(time_point& w_tsbpdtime, int32_t& w_curpktseq, int32_t seqdistance); - -#ifdef SRT_DEBUG_TSBPD_OUTJITTER - void debugTraceJitter(time_point t); -#else - void debugTraceJitter(time_point) {} -#endif /* SRT_DEBUG_TSBPD_OUTJITTER */ - - bool isRcvDataReady(); - bool isRcvDataAvailable() { return m_iLastAckPos != m_iStartPos; } - CPacket* getRcvReadyPacket(int32_t seqdistance); - - /// Set TimeStamp-Based Packet Delivery Rx Mode - /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay - /// @param [in] delay aggreed TsbPD delay - void setRcvTsbPdMode(const time_point& timebase, const duration& delay); - - /// Add packet timestamp for drift caclculation and compensation - /// @param [in] timestamp packet time stamp - /// @param [in] tsPktArrival arrival time of the packet used to extract the drift sample. - /// @param [in] rtt RTT sample - bool addRcvTsbPdDriftSample(uint32_t timestamp, const time_point& tsPktArrival, int rtt); - -#ifdef SRT_DEBUG_TSBPD_DRIFT - void printDriftHistogram(int64_t iDrift); - void printDriftOffset(int tsbPdOffset, int tsbPdDriftAvg); -#endif - - /// Get information on the 1st message in queue. - // Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] w_tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 - /// if none - /// @param [out] w_passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] w_skipseqno SRT_SEQNO_NONE or seq number of 1st unacknowledged pkt ready to play preceeded by - /// missing packets. - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base if exist packet ready-to-play - /// and larger than base - /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true - /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != SRT_SEQNO_NONE, packet ready to play preceeded by missing packets.; - /// IF skipseqno == SRT_SEQNO_NONE, no missing packet but 1st not ready to play. - bool getRcvFirstMsg(time_point& w_tsbpdtime, - bool& w_passack, - int32_t& w_skipseqno, - int32_t& w_curpktseq, - int32_t base_seq = SRT_SEQNO_NONE); - - /// Update the ACK point of the buffer. - /// @param [in] len size of data to be skip & acknowledged. - void skipData(int len); - -#if ENABLE_HEAVY_LOGGING - void reportBufferStats() const; // Heavy logging Debug only -#endif - bool empty() const - { - // This will not always return the intended value, - // that is, it may return false when the buffer really is - // empty - but it will return true then in one of next calls. - // This function will be always called again at some point - // if it returned false, and on true the connection - // is going to be broken - so this behavior is acceptable. - return m_iStartPos == m_iLastAckPos; - } - bool full() const { return m_iStartPos == (m_iLastAckPos + 1) % m_iSize; } - int capacity() const { return m_iSize; } - -private: - /// This gives up unit at index p. The unit is given back to the - /// free unit storage for further assignment for the new incoming - /// data. - size_t freeUnitAt(size_t p) - { - CUnit* u = m_pUnit[p]; - m_pUnit[p] = NULL; - size_t rmbytes = u->m_Packet.getLength(); - m_pUnitQueue->makeUnitFree(u); - return rmbytes; - } - - /// Adjust receive queue to 1st ready to play message (tsbpdtime < now). - /// Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if - /// none - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base - /// @retval true 1st packet ready to play without discontinuity (no hole) - /// @retval false tsbpdtime = 0: no packet ready to play - bool getRcvReadyMsg(time_point& w_tsbpdtime, int32_t& w_curpktseq, int upto, int base_seq = SRT_SEQNO_NONE); - -public: - /// @brief Get clock drift in microseconds. - int64_t getDrift() const { return m_tsbpd.drift(); } - -public: - int32_t getTopMsgno() const; - - void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift); - - void applyGroupTime(const time_point& timebase, bool wrapcheck, uint32_t delay, const duration& udrift); - void applyGroupDrift(const time_point& timebase, bool wrapcheck, const duration& udrift); - time_point getPktTsbPdTime(uint32_t timestamp); - int debugGetSize() const; - time_point debugGetDeliveryTime(int offset); - - size_t dropData(int len); - -private: - int extractData(char* data, int len, int p, int q, bool passack); - bool accessMsg(int& w_p, int& w_q, bool& w_passack, int64_t& w_playtime, int upto); - - /// Describes the state of the first N packets - std::string debugTimeState(size_t first_n_pkts) const; - - /// thread safe bytes counter of the Recv & Ack buffer - /// @param [in] pkts acked or removed pkts from rcv buffer (used with acked = true) - /// @param [in] bytes number of bytes added/delete (if negative) to/from rcv buffer. - /// @param [in] acked true when adding new pkt in RcvBuffer; false when acking/removing pkts to/from buffer - void countBytes(int pkts, int bytes, bool acked = false); - -private: - bool scanMsg(int& w_start, int& w_end, bool& w_passack); - - int shift(int basepos, int shift) const { return (basepos + shift) % m_iSize; } - - /// Simplified versions with ++ and --; avoid using division instruction - int shiftFwd(int basepos) const - { - if (++basepos == m_iSize) - return 0; - return basepos; - } - - int shiftBack(int basepos) const - { - if (basepos == 0) - return m_iSize - 1; - return --basepos; - } - -private: - CUnit** m_pUnit; // Array of pointed units collected in the buffer - const int m_iSize; // Size of the internal array of CUnit* items - CUnitQueue* m_pUnitQueue; // the shared unit queue - - int m_iStartPos; // HEAD: first packet available for reading - int m_iLastAckPos; // the last ACKed position (exclusive), follows the last readable - // EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1 - int m_iMaxPos; // delta between acked-TAIL and reception-TAIL - - int m_iNotch; // the starting read point of the first unit - // (this is required for stream reading mode; it's - // the position in the first unit in the list - // up to which data are already retrieved; - // in message reading mode it's unused and always 0) - - sync::Mutex m_BytesCountLock; // used to protect counters operations - int m_iBytesCount; // Number of payload bytes in the buffer - int m_iAckedPktsCount; // Number of acknowledged pkts in the buffer - int m_iAckedBytesCount; // Number of acknowledged payload bytes in the buffer - unsigned m_uAvgPayloadSz; // Average payload size for dropped bytes estimation - - CTsbpdTime m_tsbpd; - - AvgBufSize m_mavg; - -private: - CRcvBuffer(); - CRcvBuffer(const CRcvBuffer&); - CRcvBuffer& operator=(const CRcvBuffer&); -}; - -#endif // !ENABLE_NEW_RCVBUFFER - -} // namespace srt - -#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_rcv.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_rcv.h index d628c459f..d4b50fab7 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_rcv.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_rcv.h @@ -11,12 +11,9 @@ #ifndef INC_SRT_BUFFER_RCV_H #define INC_SRT_BUFFER_RCV_H -#if ENABLE_NEW_RCVBUFFER - -#include "buffer.h" // AvgBufSize +#include "buffer_tools.h" // AvgBufSize #include "common.h" #include "queue.h" -#include "sync.h" #include "tsbpd_time.h" namespace srt @@ -26,7 +23,7 @@ namespace srt * Circular receiver buffer. * * |<------------------- m_szSize ---------------------------->| - * | |<------------ m_iMaxPosInc ----------->| | + * | |<------------ m_iMaxPosOff ----------->| | * | | | | * +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+ * | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |...| 0 | m_pUnit[] @@ -45,15 +42,15 @@ namespace srt * first_nonread_pos_: */ -class CRcvBufferNew +class CRcvBuffer { typedef sync::steady_clock::time_point time_point; typedef sync::steady_clock::duration duration; public: - CRcvBufferNew(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); + CRcvBuffer(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); - ~CRcvBufferNew(); + ~CRcvBuffer(); public: /// Insert a unit into the buffer. @@ -77,14 +74,29 @@ class CRcvBufferNew /// @return the number of dropped packets. int dropAll(); - /// @brief Drop the whole message from the buffer. - /// If message number is 0, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. - /// When one packet of the message is in the range of dropping, the whole message is to be dropped. + enum DropActionIfExists { + DROP_EXISTING = 0, + KEEP_EXISTING = 1 + }; + + /// @brief Drop a sequence of packets from the buffer. + /// If @a msgno is valid, sender has requested to drop the whole message by TTL. In this case it has to also provide a pkt seqno range. + /// However, if a message has been partially acknowledged and already removed from the SND buffer, + /// the @a seqnolo might specify some position in the middle of the message, not the very first packet. + /// If those packets have been acknowledged, they must exist in the receiver buffer unless already read. + /// In this case the @a msgno should be used to determine starting packets of the message. + /// Some packets of the message can be missing on the receiver, therefore the actual drop should still be performed by pkt seqno range. + /// If message number is 0 or SRT_MSGNO_NONE, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. + /// A SOLO message packet can be kept depending on @a actionOnExisting value. + /// TODO: A message in general can be kept if all of its packets are in the buffer, depending on @a actionOnExisting value. + /// This is done to avoid dropping existing packet when the sender was asked to re-transmit a packet from an outdated loss report, + /// which is already not available in the SND buffer. /// @param seqnolo sequence number of the first packet in the dropping range. /// @param seqnohi sequence number of the last packet in the dropping range. /// @param msgno message number to drop (0 if unknown) + /// @param actionOnExisting Should an exising SOLO packet be dropped from the buffer or preserved? /// @return the number of packets actually dropped. - int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno); + int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno, DropActionIfExists actionOnExisting); /// Read the whole message from one or several packets. /// @@ -130,9 +142,8 @@ class CRcvBufferNew const int iRBufSeqNo = getStartSeqNo(); if (CSeqNo::seqcmp(iRBufSeqNo, iFirstUnackSeqNo) >= 0) // iRBufSeqNo >= iFirstUnackSeqNo { - // Full capacity is available, still don't want to encourage extra packets to come. - // Note: CSeqNo::seqlen(n, n) returns 1. - return capacity() - CSeqNo::seqlen(iFirstUnackSeqNo, iRBufSeqNo) + 1; + // Full capacity is available. + return capacity(); } // Note: CSeqNo::seqlen(n, n) returns 1. @@ -140,13 +151,14 @@ class CRcvBufferNew } /// @brief Checks if the buffer has packets available for reading regardless of the TSBPD. + /// A message is available for reading only if all of its packets are present in the buffer. /// @return true if there are packets available for reading, false otherwise. bool hasAvailablePackets() const; /// Query how many data has been continuously received (for reading) and available for reading out /// regardless of the TSBPD. /// TODO: Rename to countAvailablePackets(). - /// @return size of valid (continous) data for reading. + /// @return size of valid (continuous) data for reading. int getRcvDataSize() const; /// Get the number of packets, bytes and buffer timespan. @@ -165,11 +177,11 @@ class CRcvBufferNew /// Parameters (of the 1st packet queue, ready to play or not): /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if /// none - /// @param [out] passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] skipseqno -1 or seq number of 1st unacknowledged pkt ready to play preceeded by missing packets. + /// @param [out] passack true if 1st ready packet is not yet acknowledged (allowed to be delivered to the app) + /// @param [out] skipseqno -1 or sequence number of 1st unacknowledged packet (after one or more missing packets) that is ready to play. /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != -1, packet ready to play preceeded by missing packets.; + /// IF skipseqno != -1, packet ready to play preceded by missing packets.; /// IF skipseqno == -1, no missing packet but 1st not ready to play. PacketInfo getFirstValidPacketInfo() const; @@ -185,7 +197,7 @@ class CRcvBufferNew bool empty() const { - return (m_iMaxPosInc == 0); + return (m_iMaxPosOff == 0); } /// Return buffer capacity. @@ -227,6 +239,18 @@ class CRcvBufferNew inline int incPos(int pos, int inc = 1) const { return (pos + inc) % m_szSize; } inline int decPos(int pos) const { return (pos - 1) >= 0 ? (pos - 1) : int(m_szSize - 1); } inline int offPos(int pos1, int pos2) const { return (pos2 >= pos1) ? (pos2 - pos1) : int(m_szSize + pos2 - pos1); } + inline int cmpPos(int pos2, int pos1) const + { + // XXX maybe not the best implementation, but this keeps up to the rule + const int off1 = pos1 >= m_iStartPos ? pos1 - m_iStartPos : pos1 + (int)m_szSize - m_iStartPos; + const int off2 = pos2 >= m_iStartPos ? pos2 - m_iStartPos : pos2 + (int)m_szSize - m_iStartPos; + + return off2 - off1; + } + + // NOTE: Assumes that pUnit != NULL + CPacket& packetAt(int pos) { return m_entries[pos].pUnit->m_Packet; } + const CPacket& packetAt(int pos) const { return m_entries[pos].pUnit->m_Packet; } private: void countBytes(int pkts, int bytes); @@ -268,7 +292,7 @@ class CRcvBufferNew int getTimespan_ms() const; private: - // TODO: Call makeUnitGood upon assignment, and makeUnitFree upon clearing. + // TODO: Call makeUnitTaken upon assignment, and makeUnitFree upon clearing. // TODO: CUnitPtr is not in use at the moment, but may be a smart pointer. // class CUnitPtr // { @@ -313,7 +337,7 @@ class CRcvBufferNew int m_iStartSeqNo; int m_iStartPos; // the head position for I/O (inclusive) int m_iFirstNonreadPos; // First position that can't be read (<= m_iLastAckPos) - int m_iMaxPosInc; // the furthest data position + int m_iMaxPosOff; // the furthest data position int m_iNotch; // the starting read point of the first unit size_t m_numOutOfOrderPackets; // The number of stored packets with "inorder" flag set to false @@ -326,7 +350,7 @@ class CRcvBufferNew /// Set TimeStamp-Based Packet Delivery Rx Mode /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay /// @param [in] wrap Is in wrapping period - /// @param [in] delay aggreed TsbPD delay + /// @param [in] delay agreed TsbPD delay /// /// @return 0 void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); @@ -344,6 +368,8 @@ class CRcvBufferNew time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; void updateTsbPdTimeBase(uint32_t usPktTimestamp); + bool isTsbPd() const { return m_tsbpd.isEnabled(); } + /// Form a string of the current buffer fullness state. /// number of packets acknowledged, TSBPD readiness, etc. std::string strFullnessState(int iFirstUnackSeqNo, const time_point& tsNow) const; @@ -363,5 +389,4 @@ class CRcvBufferNew } // namespace srt -#endif // ENABLE_NEW_RCVBUFFER #endif // INC_SRT_BUFFER_RCV_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_snd.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_snd.h new file mode 100644 index 000000000..4440b9bfd --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_snd.h @@ -0,0 +1,259 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_SND_H +#define INC_SRT_BUFFER_SND_H + +#include "srt.h" +#include "packet.h" +#include "buffer_tools.h" + +// The notation used for "circular numbers" in comments: +// The "cicrular numbers" are numbers that when increased up to the +// maximum become zero, and similarly, when the zero value is decreased, +// it turns into the maximum value minus one. This wrapping works the +// same for adding and subtracting. Circular numbers cannot be multiplied. + +// Operations done on these numbers are marked with additional % character: +// a %> b : a is later than b +// a ++% (++%a) : shift a by 1 forward +// a +% b : shift a by b +// a == b : equality is same as for just numbers + +namespace srt { + +class CSndBuffer +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the buffer is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// @brief CSndBuffer constructor. + /// @param size initial number of blocks (each block to store one packet payload). + /// @param maxpld maximum packet payload (including auth tag). + /// @param authtag auth tag length in bytes (16 for GCM, 0 otherwise). + CSndBuffer(int size = 32, int maxpld = 1500, int authtag = 0); + ~CSndBuffer(); + +public: + /// Insert a user buffer into the sending list. + /// For @a w_mctrl the following fields are used: + /// INPUT: + /// - msgttl: timeout for retransmitting the message, if lost + /// - inorder: request to deliver the message in order of sending + /// - srctime: local time as a base for packet's timestamp (0 if unused) + /// - pktseq: sequence number to be stamped on the packet (-1 if unused) + /// - msgno: message number to be stamped on the packet (-1 if unused) + /// OUTPUT: + /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) + /// - pktseq: sequence number to be stamped on the next packet + /// - msgno: message number stamped on the packet + /// @param [in] data pointer to the user data block. + /// @param [in] len size of the block. + /// @param [inout] w_mctrl Message control data + SRT_ATTR_EXCLUDES(m_BufLock) + void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); + + /// Read a block of data from file and insert it into the sending list. + /// @param [in] ifs input file stream. + /// @param [in] len size of the block. + /// @return actual size of data added from the file. + SRT_ATTR_EXCLUDES(m_BufLock) + int addBufferFromFile(std::fstream& ifs, int len); + + /// Find data position to pack a DATA packet from the furthest reading point. + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [in] kflags Odd|Even crypto key flag + /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. + /// @return Actual length of data read. + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); + + /// Peek an information on the next original data packet to send. + /// @return origin time stamp of the next packet; epoch start time otherwise. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point peekNextOriginal() const; + + /// Find data position to pack a DATA packet for a retransmission. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [out] msglen length of the message + /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); + + /// Get the time of the last retransmission (if any) of the DATA packet. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// + /// @return Last time of the last retransmission event for the corresponding DATA packet. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point getPacketRexmitTime(const int offset); + + /// Update the ACK point and may release/unmap/return the user data according to the flag. + /// @param [in] offset number of packets acknowledged. + int32_t getMsgNoAt(const int offset); + + void ackData(int offset); + + /// Read size of data still in the sending list. + /// @return Current size of the data in the sending list. + int getCurrBufSize() const; + + SRT_ATTR_EXCLUDES(m_BufLock) + int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); + + void updAvgBufSize(const time_point& time); + int getAvgBufSize(int& bytes, int& timespan); + int getCurrBufSize(int& bytes, int& timespan) const; + + + /// Het maximum payload length per packet. + int getMaxPacketLen() const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen) const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @param iMaxPktLen the maximum payload length of the packet (the value returned from getMaxPacketLen()). + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen, int iMaxPktLen) const; + + /// @brief Get the buffering delay of the oldest message in the buffer. + /// @return the delay value. + SRT_ATTR_EXCLUDES(m_BufLock) + duration getBufferingDelay(const time_point& tnow) const; + + uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_rateEstimator.getInputRate(); } + + void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } + + const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } + + void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } + +private: + void increase(); + +private: + mutable sync::Mutex m_BufLock; // used to synchronize buffer operation + + struct Block + { + char* m_pcData; // pointer to the data block + int m_iLength; // payload length of the block (excluding auth tag). + + int32_t m_iMsgNoBitset; // message number + int32_t m_iSeqNo; // sequence number for scheduling + time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. + time_point m_tsRexmitTime; // packet retransmission time + int m_iTTL; // time to live (milliseconds) + + Block* m_pNext; // next block + + int32_t getMsgSeq() + { + // NOTE: this extracts message ID with regard to REXMIT flag. + // This is valid only for message ID that IS GENERATED in this instance, + // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter + // for the peer that it uses LESS bits to represent the message. + return m_iMsgNoBitset & MSGNO_SEQ::mask; + } + + } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; + + // m_pBlock: The head pointer + // m_pFirstBlock: The first block + // m_pCurrBlock: The current block + // m_pLastBlock: The last block (if first == last, buffer is empty) + + struct Buffer + { + char* m_pcData; // buffer + int m_iSize; // size + Buffer* m_pNext; // next buffer + } * m_pBuffer; // physical buffer + + int32_t m_iNextMsgNo; // next message number + + int m_iSize; // buffer size (number of packets) + const int m_iBlockLen; // maximum length of a block holding packet payload and AUTH tag (excluding packet header). + const int m_iAuthTagSize; // Authentication tag size (if GCM is enabled). + int m_iCount; // number of used blocks + + int m_iBytesCount; // number of payload bytes in queue + time_point m_tsLastOriginTime; + + AvgBufSize m_mavg; + CRateEstimator m_rateEstimator; + +private: + CSndBuffer(const CSndBuffer&); + CSndBuffer& operator=(const CSndBuffer&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_tools.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_tools.h new file mode 100644 index 000000000..e6ce89d0d --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/buffer_tools.h @@ -0,0 +1,201 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_TOOLS_H +#define INC_SRT_BUFFER_TOOLS_H + +#include "common.h" + +namespace srt +{ + +/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) +class AvgBufSize +{ + typedef sync::steady_clock::time_point time_point; + +public: + AvgBufSize() + : m_dBytesCountMAvg(0.0) + , m_dCountMAvg(0.0) + , m_dTimespanMAvg(0.0) + { + } + +public: + bool isTimeToUpdate(const time_point& now) const; + void update(const time_point& now, int pkts, int bytes, int timespan_ms); + +public: + inline double pkts() const { return m_dCountMAvg; } + inline double timespan_ms() const { return m_dTimespanMAvg; } + inline double bytes() const { return m_dBytesCountMAvg; } + +private: + time_point m_tsLastSamplingTime; + double m_dBytesCountMAvg; + double m_dCountMAvg; + double m_dTimespanMAvg; +}; + +/// The class to estimate source bitrate based on samples submitted to the buffer. +/// Is currently only used by the CSndBuffer. +class CRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; +public: + CRateEstimator(); + +public: + uint64_t getInRatePeriod() const { return m_InRatePeriod; } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_iInRateBps; } + + void setInputRateSmpPeriod(int period); + + /// Update input rate calculation. + /// @param [in] time current time + /// @param [in] pkts number of packets newly added to the buffer + /// @param [in] bytes number of payload bytes in those newly added packets + void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); + + void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } + +private: // Constants + static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms + static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms + static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload + static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; + +private: + int m_iInRatePktsCount; // number of payload packets added since InRateStartTime. + int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime. + time_point m_tsInRateStartTime; + uint64_t m_InRatePeriod; // usec + int m_iInRateBps; // Input Rate in Bytes/sec +}; + + +class CSndRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + +public: + CSndRateEstimator(const time_point& tsNow); + + /// Add sample. + /// @param [in] time sample (sending) time. + /// @param [in] pkts number of packets in the sample. + /// @param [in] bytes number of payload bytes in the sample. + void addSample(const time_point& time, int pkts = 0, size_t bytes = 0); + + /// Retrieve estimated bitrate in bytes per second + int getRate() const { return m_iRateBps; } + + /// Retrieve estimated bitrate in bytes per second inluding the current sampling interval. + int getCurrentRate() const; + +private: + static const int NUM_PERIODS = 10; + static const int SAMPLE_DURATION_MS = 100; // 100 ms + struct Sample + { + int m_iPktsCount; // number of payload packets + int m_iBytesCount; // number of payload bytes + + void reset() + { + m_iPktsCount = 0; + m_iBytesCount = 0; + } + + Sample() + : m_iPktsCount(0) + , m_iBytesCount(0) + { + } + + Sample(int iPkts, int iBytes) + : m_iPktsCount(iPkts) + , m_iBytesCount(iBytes) + { + } + + Sample operator+(const Sample& other) + { + return Sample(m_iPktsCount + other.m_iPktsCount, m_iBytesCount + other.m_iBytesCount); + } + + Sample& operator+=(const Sample& other) + { + *this = *this + other; + return *this; + } + + bool empty() const { return m_iPktsCount == 0; } + }; + + int incSampleIdx(int val, int inc = 1) const; + + Sample m_Samples[NUM_PERIODS]; + + time_point m_tsFirstSampleTime; //< Start time of the first sameple. + int m_iFirstSampleIdx; //< Index of the first sample. + int m_iCurSampleIdx; //< Index of the current sample being collected. + int m_iRateBps; // Input Rate in Bytes/sec +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/cache.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/cache.h index 0dd57ba01..47633706a 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/cache.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/cache.h @@ -253,7 +253,7 @@ class CInfoBlock CInfoBlock& copyFrom(const CInfoBlock& obj); CInfoBlock(const CInfoBlock& src) { copyFrom(src); } CInfoBlock& operator=(const CInfoBlock& src) { return copyFrom(src); } - bool operator==(const CInfoBlock& obj); + bool operator==(const CInfoBlock& obj) const; CInfoBlock* clone(); int getKey(); void release() {} diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/channel.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/channel.h index 0255102fe..1bfcc47c8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/channel.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/channel.h @@ -115,9 +115,10 @@ class CChannel /// Send a packet to the given address. /// @param [in] addr pointer to the destination address. /// @param [in] packet reference to a CPacket entity. + /// @param [in] src source address to sent on an outgoing packet (if not ANY) /// @return Actual size of data sent. - int sendto(const sockaddr_any& addr, srt::CPacket& packet) const; + int sendto(const sockaddr_any& addr, srt::CPacket& packet, const sockaddr_any& src) const; /// Receive a packet from the channel and record the source address. /// @param [in] addr pointer to the source address. @@ -128,6 +129,21 @@ class CChannel void setConfig(const CSrtMuxerConfig& config); + void getSocketOption(int level, int sockoptname, char* pw_dataptr, socklen_t& w_len, int& w_status); + + template + Type sockopt(int level, int sockoptname, Type deflt) + { + Type retval; + socklen_t socklen = sizeof retval; + int status; + getSocketOption(level, sockoptname, ((char*)&retval), (socklen), (status)); + if (status == -1) + return deflt; + + return retval; + } + /// Get the IP TTL. /// @param [in] ttl IP Time To Live. /// @return TTL. @@ -160,6 +176,121 @@ class CChannel // although the object itself isn't considered modified. mutable CSrtMuxerConfig m_mcfg; // Note: ReuseAddr is unused and ineffective. sockaddr_any m_BindAddr; + + // This feature is not enabled on Windows, for now. + // This is also turned off in case of MinGW +#ifdef SRT_ENABLE_PKTINFO + bool m_bBindMasked; // True if m_BindAddr is INADDR_ANY. Need for quick check. + + // Calculating the required space is extremely tricky, and whereas on most + // platforms it's possible to define it this way: + // + // size_t s = max( CMSG_SPACE(sizeof(in_pktinfo)), CMSG_SPACE(sizeof(in6_pktinfo)) ) + // + // ...on some platforms however CMSG_SPACE macro can't be resolved as constexpr. + // + // This structure is exclusively used to determine the required size for + // CMSG buffer so that it can be allocated in a solid block with CChannel. + // NOT TO BE USED to access any data inside the CMSG message. + struct CMSGNodeIPv4 + { + in_pktinfo in4; + size_t extrafill; + cmsghdr hdr; + }; + + struct CMSGNodeIPv6 + { + in6_pktinfo in6; + size_t extrafill; + cmsghdr hdr; + }; + + // This is 'mutable' because it's a utility buffer defined here + // to avoid unnecessary re-allocations. + mutable char m_acCmsgRecvBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + mutable char m_acCmsgSendBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just after + // calling ::recvmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in receiving mode. + sockaddr_any getTargetAddress(const msghdr& msg) const + { + // Loop through IP header messages + cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(((msghdr*)&msg), cmsg)) + { + // This should be safe - this packet contains always either + // IPv4 headers or IPv6 headers. + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) + { + in_pktinfo *dest_ip_ptr = (in_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi_addr, 0); + } + + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + in6_pktinfo* dest_ip_ptr = (in6_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi6_addr, 0); + } + } + + // Fallback for an error + return sockaddr_any(m_BindAddr.family()); + } + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just before + // calling ::sendmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in sending mode. + bool setSourceAddress(msghdr& mh, const sockaddr_any& adr) const + { + // In contrast to an advice followed on the net, there's no case of putting + // both IPv4 and IPv6 ancillary data, case we could have them. Only one + // IP version is used and it's the version as found in @a adr, which should + // be the version used for binding. + + if (adr.family() == AF_INET) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + // after initializing msghdr & control data to CMSG_SPACE(sizeof(struct in_pktinfo)) + cmsg_send->cmsg_level = IPPROTO_IP; + cmsg_send->cmsg_type = IP_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + in_pktinfo* pktinfo = (in_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi_ifindex = 0; + pktinfo->ipi_spec_dst = adr.sin.sin_addr; + + return true; + } + + if (adr.family() == AF_INET6) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in6_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + cmsg_send->cmsg_level = IPPROTO_IPV6; + cmsg_send->cmsg_type = IPV6_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); + in6_pktinfo* pktinfo = (in6_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi6_ifindex = 0; + pktinfo->ipi6_addr = adr.sin6.sin6_addr; + + return true; + } + + return false; + } + +#endif // SRT_ENABLE_PKTINFO + }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/common.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/common.h index 227a91861..5021fa5a8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/common.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/common.h @@ -53,7 +53,6 @@ modified by #ifndef INC_SRT_COMMON_H #define INC_SRT_COMMON_H -#define _CRT_SECURE_NO_WARNINGS 1 // silences windows complaints for sscanf #include #include #include @@ -1393,8 +1392,11 @@ inline ATR_CONSTEXPR uint32_t SrtVersion(int major, int minor, int patch) inline int32_t SrtParseVersion(const char* v) { int major, minor, patch; +#if defined(_MSC_VER) + int result = sscanf_s(v, "%d.%d.%d", &major, &minor, &patch); +#else int result = sscanf(v, "%d.%d.%d", &major, &minor, &patch); - +#endif if (result != 3) { return 0; @@ -1409,12 +1411,16 @@ inline std::string SrtVersionString(int version) int minor = (version/0x100)%0x100; int major = version/0x10000; - char buf[20]; - sprintf(buf, "%d.%d.%d", major, minor, patch); + char buf[22]; +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(buf, sizeof(buf) - 1, "%d.%d.%d", major, minor, patch); +#else + snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch); +#endif return buf; } -bool SrtParseConfig(std::string s, SrtConfig& w_config); +bool SrtParseConfig(const std::string& s, SrtConfig& w_config); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/congctl.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/congctl.h index b957dbdd0..a2264b594 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/congctl.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/congctl.h @@ -52,8 +52,8 @@ class SrtCongestion struct IsName { - std::string n; - IsName(std::string nn): n(nn) {} + const std::string n; + IsName(const std::string& nn): n(nn) {} bool operator()(NamePtr np) { return n == np.first; } }; diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/core.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/core.h index fa58ca7c2..71c955c33 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/core.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/core.h @@ -59,7 +59,7 @@ modified by #include "srt.h" #include "common.h" #include "list.h" -#include "buffer.h" +#include "buffer_snd.h" #include "buffer_rcv.h" #include "window.h" #include "packet.h" @@ -288,7 +288,7 @@ class CUDT { #if ENABLE_LOGGING std::ostringstream os; - os << "@" << m_SocketID << ":"; + os << "@" << m_SocketID << ": "; return os.str(); #else return ""; @@ -312,8 +312,10 @@ class CUDT int32_t schedSeqNo() const { return m_iSndNextSeqNo; } bool overrideSndSeqNo(int32_t seq); +#if ENABLE_BONDING sync::steady_clock::time_point lastRspTime() const { return m_tsLastRspTime.load(); } sync::steady_clock::time_point freshActivationStart() const { return m_tsFreshActivation; } +#endif int32_t rcvSeqNo() const { return m_iRcvCurrSeqNo; } int flowWindowSize() const { return m_iFlowWindowSize; } @@ -371,27 +373,34 @@ class CUDT int minSndSize(int len = 0) const { const int ps = (int) maxPayloadSize(); - if (len == 0) // wierd, can't use non-static data member as default argument! + if (len == 0) // weird, can't use non-static data member as default argument! len = ps; return m_config.bMessageAPI ? (len+ps-1)/ps : 1; } - int32_t makeTS(const time_point& from_time) const + static int32_t makeTS(const time_point& from_time, const time_point& tsStartTime) { // NOTE: // - This calculates first the time difference towards start time. // - This difference value is also CUT OFF THE SEGMENT information // (a multiple of MAX_TIMESTAMP+1) // So, this can be simply defined as: TS = (RTS - STS) % (MAX_TIMESTAMP+1) - // XXX Would be nice to check if local_time > m_tsStartTime, - // otherwise it may go unnoticed with clock skew. - return (int32_t) sync::count_microseconds(from_time - m_stats.tsStartTime); + SRT_ASSERT(from_time >= tsStartTime); + return (int32_t) sync::count_microseconds(from_time - tsStartTime); } - void setPacketTS(CPacket& p, const time_point& local_time) - { - p.m_iTimeStamp = makeTS(local_time); - } + /// @brief Set the timestamp field of the packet using the provided value (no check) + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setPacketTS(CPacket& p, const time_point& ts); + + /// @brief Set the timestamp field of the packet according the TSBPD mode. + /// Also checks the connection start time (m_tsStartTime). + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. Ignored if m_bPeerTsbPd is false. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setDataPacketTS(CPacket& p, const time_point& ts); // Utility used for closing a listening socket // immediately to free the socket @@ -416,11 +425,7 @@ class CUDT SRTU_PROPERTY_RO(SRTSOCKET, id, m_SocketID); SRTU_PROPERTY_RO(bool, isClosing, m_bClosing); -#if ENABLE_NEW_RCVBUFFER - SRTU_PROPERTY_RO(srt::CRcvBufferNew*, rcvBuffer, m_pRcvBuffer); -#else - SRTU_PROPERTY_RO(CRcvBuffer*, rcvBuffer, m_pRcvBuffer); -#endif + SRTU_PROPERTY_RO(srt::CRcvBuffer*, rcvBuffer, m_pRcvBuffer); SRTU_PROPERTY_RO(bool, isTLPktDrop, m_bTLPktDrop); SRTU_PROPERTY_RO(bool, isSynReceiving, m_config.bSynRecving); SRTU_PROPERTY_RR(sync::Condition*, recvDataCond, &m_RecvDataCond); @@ -441,16 +446,13 @@ class CUDT private: /// initialize a UDT entity and bind to a local address. - void open(); /// Start listening to any connection request. - void setListenState(); /// Connect to a UDT entity listening at address "peer". /// @param peer [in] The address of the listening UDT entity. - void startConnect(const sockaddr_any& peer, int32_t forced_isn); /// Process the response handshake packet. Failure reasons can be: @@ -461,7 +463,6 @@ class CUDT /// @retval 0 Connection successful /// @retval 1 Connection in progress (m_ConnReq turned into RESPONSE) /// @retval -1 Connection failed - SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processConnectResponse(const CPacket& pkt, CUDTException* eout) ATR_NOEXCEPT; @@ -484,15 +485,20 @@ class CUDT /// @param rst Current read status to know if the HS packet was freshly received from the peer, or this is only a periodic update (RST_AGAIN) SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processRendezvous(const CPacket* response, const sockaddr_any& serv_addr, EReadStatus, CPacket& reqpkt); + void sendRendezvousRejection(const sockaddr_any& serv_addr, CPacket& request); + + /// Create the CryptoControl object based on the HS packet. + SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) + bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException* eout); - /// Create the CryptoControl object based on the HS packet. Allocates sender and receiver buffers and loss lists. + /// Allocates sender and receiver buffers and loss lists. SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) - bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException *eout); + bool prepareBuffers(CUDTException* eout); SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus postConnect(const CPacket* response, bool rendezvous, CUDTException* eout) ATR_NOEXCEPT; - SRT_ATR_NODISCARD bool applyResponseSettings() ATR_NOEXCEPT; + SRT_ATR_NODISCARD bool applyResponseSettings(const CPacket* hspkt /*[[nullable]]*/) ATR_NOEXCEPT; SRT_ATR_NODISCARD EConnectStatus processAsyncConnectResponse(const CPacket& pkt) ATR_NOEXCEPT; SRT_ATR_NODISCARD bool processAsyncConnectRequest(EReadStatus rst, EConnectStatus cst, const CPacket* response, const sockaddr_any& serv_addr); SRT_ATR_NODISCARD EConnectStatus craftKmResponse(uint32_t* aw_kmdata, size_t& w_kmdatasize); @@ -662,8 +668,14 @@ class CUDT /// the receiver fresh loss list. void unlose(const CPacket& oldpacket); void dropFromLossLists(int32_t from, int32_t to); + bool getFirstNoncontSequence(int32_t& w_seq, std::string& w_log_reason); + + SRT_ATTR_EXCLUDES(m_ConnectionLock) + void checkSndTimers(); + + /// @brief Check and perform KM refresh if needed. + void checkSndKMRefresh(); - void checkSndTimers(Whether2RegenKm regen = DONT_REGEN_KM); void handshakeDone() { m_iSndHsRetryCnt = 0; @@ -708,18 +720,17 @@ class CUDT SRT_ATTR_EXCLUDES(m_RcvBufferLock) bool isRcvBufferReady() const; + SRT_ATTR_REQUIRES(m_RcvBufferLock) + bool isRcvBufferReadyNoLock() const; + // TSBPD thread main function. static void* tsbpd(void* param); -#if ENABLE_NEW_RCVBUFFER - /// Drop too late packets (receiver side). Updaet loss lists and ACK positions. + /// Drop too late packets (receiver side). Update loss lists and ACK positions. /// The @a seqno packet itself is not dropped. /// @param seqno [in] The sequence number of the first packets following those to be dropped. /// @return The number of packets dropped. int rcvDropTooLateUpTo(int seqno); -#endif - - void updateForgotten(int seqlen, int32_t lastack, int32_t skiptoseqno); static loss_seqs_t defaultPacketArrival(void* vself, CPacket& pkt); static loss_seqs_t groupPacketArrival(void* vself, CPacket& pkt); @@ -811,6 +822,9 @@ class CUDT CSndBuffer* m_pSndBuffer; // Sender buffer CSndLossList* m_pSndLossList; // Sender loss list CPktTimeWindow<16, 16> m_SndTimeWindow; // Packet sending time window +#ifdef ENABLE_MAXREXMITBW + CSndRateEstimator m_SndRexmitRate; // Retransmission rate estimation. +#endif atomic_duration m_tdSendInterval; // Inter-packet time, in CPU clock cycles @@ -826,6 +840,7 @@ class CUDT duration m_tdACKInterval; // ACK interval duration m_tdNAKInterval; // NAK interval + SRT_ATTR_GUARDED_BY(m_RecvAckLock) atomic_time_point m_tsLastRspTime; // Timestamp of last response from the peer time_point m_tsLastRspAckTime; // (SND) Timestamp of last ACK from the peer @@ -851,7 +866,7 @@ class CUDT // and this is the sequence number that refers to the block at position [0]. Upon acknowledgement, // this value is shifted to the acknowledged position, and the blocks are removed from the // m_pSndBuffer buffer up to excluding this sequence number. - // XXX CONSIDER removing this field and give up the maintenance of this sequence number + // XXX CONSIDER removing this field and giving up the maintenance of this sequence number // to the sending buffer. This way, extraction of an old packet for retransmission should // require only the lost sequence number, and how to find the packet with this sequence // will be up to the sending buffer. @@ -894,14 +909,22 @@ class CUDT SRT_ATTR_GUARDED_BY(m_RecvAckLock) int32_t m_iReXmitCount; // Re-Transmit Count since last ACK + time_point m_tsLogSlowDown; // The last time a log message from the "slow down" group was shown. + // The "slow down" group of logs are those that can be printed too often otherwise, but can't be turned off (warnings and errors). + // Currently only used by decryption failure message, therefore no mutex protection needed. + + /// @brief Check if a frequent log can be shown. + /// @param tnow current time + /// @return true if it is ok to print a frequent log message. + bool frequentLogAllowed(const time_point& tnow) const; + private: // Receiving related data -#if ENABLE_NEW_RCVBUFFER - CRcvBufferNew* m_pRcvBuffer; //< Receiver buffer -#else CRcvBuffer* m_pRcvBuffer; //< Receiver buffer -#endif + SRT_ATTR_GUARDED_BY(m_RcvLossLock) CRcvLossList* m_pRcvLossList; //< Receiver loss list + SRT_ATTR_GUARDED_BY(m_RcvLossLock) std::deque m_FreshLoss; //< Lost sequence already added to m_pRcvLossList, but not yet sent UMSG_LOSSREPORT for. + int m_iReorderTolerance; //< Current value of dynamic reorder tolerance int m_iConsecEarlyDelivery; //< Increases with every OOO packet that came m_iRcvCurrSeqNo; // (RCV) Largest received sequence number. RcvQTh, TSBPDTh. int32_t m_iRcvCurrPhySeqNo; // Same as m_iRcvCurrSeqNo, but physical only (disregarding a filter) - + bool m_bBufferWasFull; // Indicate that RX buffer was full last time a ack was sent int32_t m_iPeerISN; // Initial Sequence Number of the peer side uint32_t m_uPeerSrtVersion; @@ -959,7 +981,7 @@ class CUDT mutable sync::Mutex m_RcvBufferLock; // Protects the state of the m_pRcvBuffer // Protects access to m_iSndCurrSeqNo, m_iSndLastAck - sync::Mutex m_RecvAckLock; // Protects the state changes while processing incomming ACK (SRT_EPOLL_OUT) + sync::Mutex m_RecvAckLock; // Protects the state changes while processing incoming ACK (SRT_EPOLL_OUT) sync::Condition m_RecvDataCond; // used to block "srt_recv*" when there is no data. Use together with m_RecvLock sync::Mutex m_RecvLock; // used to synchronize "srt_recv*" call, protects TSBPD drift updates (CRcvBuffer::isRcvDataReady()) @@ -1036,32 +1058,50 @@ class CUDT void updateSndLossListOnACK(int32_t ackdata_seqno); /// Pack a packet from a list of lost packets. - /// /// @param packet [in, out] a packet structure to fill - /// @param origintime [in, out] origin timestamp of the packet - /// /// @return payload size on success, <=0 on failure - int packLostData(CPacket &packet, time_point &origintime); + int packLostData(CPacket &packet); /// Pack a unique data packet (never sent so far) in CPacket for sending. - /// /// @param packet [in, out] a CPacket structure to fill. - /// @param origintime [in, out] origin timestamp of the packet. /// /// @return true if a packet has been packets; false otherwise. - bool packUniqueData(CPacket& packet, time_point& origintime); + bool packUniqueData(CPacket& packet); /// Pack in CPacket the next data to be send. /// - /// @param packet [in, out] a CPacket structure to fill + /// @param packet [out] a CPacket structure to fill + /// @param nexttime [out] Time when this socket should be next time picked up for processing. + /// @param src_addr [out] Source address to pass to channel's sendto /// - /// @return A pair of values is returned (is_payload_valid, timestamp). - /// If is_payload_valid is false, there was nothing packed for sending, - /// and the timestamp value should be ignored. - /// The timestamp is the full source/origin timestamp of the data. - std::pair packData(CPacket& packet); + /// @retval true A packet was extracted for sending, the socket should be rechecked at @a nexttime + /// @retval false Nothing was extracted for sending, @a nexttime should be ignored + bool packData(CPacket& packet, time_point& nexttime, sockaddr_any& src_addr); int processData(CUnit* unit); + + /// This function passes the incoming packet to the initial processing + /// (like packet filter) and is about to store it effectively to the + /// receiver buffer and do some postprocessing (decryption) if necessary + /// and report the status thereof. + /// + /// @param incoming [in] The packet coming from the network medium + /// @param w_new_inserted [out] Set false, if the packet already exists, otherwise true (packet added) + /// @param w_was_sent_in_order [out] Set false, if the packet was belated, but had no R flag set. + /// @param w_srt_loss_seqs [out] Gets inserted a loss, if this function has detected it. + /// + /// @return 0 The call was successful (regardless if the packet was accepted or not). + /// @return -1 The call has failed: no space left in the buffer. + /// @return -2 The incoming packet exceeds the expected sequence by more than a length of the buffer (irrepairable discrepancy). + int handleSocketPacketReception(const std::vector& incoming, bool& w_new_inserted, bool& w_was_sent_in_order, CUDT::loss_seqs_t& w_srt_loss_seqs); + + /// Get the packet's TSBPD time. + /// The @a grp passed by void* is not used yet + /// and shall not be used when ENABLE_BONDING=0. + time_point getPktTsbPdTime(void* grp, const CPacket& packet); + + /// Checks and spawns the TSBPD thread if required. + int checkLazySpawnTsbPdThread(); void processClose(); /// Process the request after receiving the handshake from caller. @@ -1075,12 +1115,7 @@ class CUDT static void addLossRecord(std::vector& lossrecord, int32_t lo, int32_t hi); int32_t bake(const sockaddr_any& addr, int32_t previous_cookie = 0, int correction = 0); - /// @brief Acknowledge reading position up to the @p seq. - /// Updates m_iRcvLastAck and m_iRcvLastSkipAck to @p seq. - /// @param seq first unacknowledged packet sequence number. - void ackDataUpTo(int32_t seq); - -#if ENABLE_BONDING && ENABLE_NEW_RCVBUFFER +#if ENABLE_BONDING /// @brief Drop packets in the recv buffer behind group_recv_base. /// Updates m_iRcvLastSkipAck if it's behind group_recv_base. void dropToGroupRecvBase(); @@ -1088,9 +1123,6 @@ class CUDT void processKeepalive(const CPacket& ctrlpkt, const time_point& tsArrival); - /// Locks m_RcvBufferLock and retrieves the available size of the receiver buffer. - SRT_ATTR_EXCLUDES(m_RcvBufferLock) - size_t getAvailRcvBufferSizeLock() const; /// Retrieves the available size of the receiver buffer. /// Expects that m_RcvBufferLock is locked. @@ -1120,10 +1152,12 @@ class CUDT static const int PACKETPAIR_MASK = 0xF; private: // Timers functions +#if ENABLE_BONDING time_point m_tsFreshActivation; // GROUPS: time of fresh activation of the link, or 0 if past the activation phase or idle time_point m_tsUnstableSince; // GROUPS: time since unexpected ACK delay experienced, or 0 if link seems healthy time_point m_tsWarySince; // GROUPS: time since an unstable link has first some response - +#endif + static const int BECAUSE_NO_REASON = 0, // NO BITS BECAUSE_ACK = 1 << 0, BECAUSE_LITEACK = 1 << 1, @@ -1142,6 +1176,7 @@ class CUDT CSndQueue* m_pSndQueue; // packet sending queue CRcvQueue* m_pRcvQueue; // packet receiving queue sockaddr_any m_PeerAddr; // peer address + sockaddr_any m_SourceAddr; // override UDP source address with this one when sending uint32_t m_piSelfIP[4]; // local UDP IP address CSNode* m_pSNode; // node information for UDT list used in snd queue CRNode* m_pRNode; // node information for UDT list used in rcv queue diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/crypto.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/crypto.h index 2c2b35250..370d5529c 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/crypto.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/crypto.h @@ -50,8 +50,6 @@ const size_t SRT_KMR_KMSTATE = 0; #define SRT_CMD_MAXSZ HCRYPT_MSG_KM_MAX_SZ /* Maximum SRT custom messages payload size (bytes) */ const size_t SRTDATA_MAXSIZE = SRT_CMD_MAXSZ/sizeof(uint32_t); -enum Whether2RegenKm {DONT_REGEN_KM = 0, REGEN_KM = 1}; - class CCryptoControl { SRTSOCKET m_SocketID; @@ -69,10 +67,12 @@ class CCryptoControl // putting the whole HaiCrypt_Cfg object here. int m_KmRefreshRatePkt; int m_KmPreAnnouncePkt; + int m_iCryptoMode; HaiCrypt_Secret m_KmSecret; //Key material shared secret // Sender sync::steady_clock::time_point m_SndKmLastTime; + sync::Mutex m_mtxLock; // A mutex to protect concurrent access to CCryptoControl. struct { unsigned char Msg[HCRYPT_MSG_KM_MAX_SZ]; size_t MsgLen; @@ -87,6 +87,8 @@ class CCryptoControl public: static void globalInit(); + static bool isAESGCMSupported(); + bool sendingAllowed() { // This function is called to state as to whether the @@ -109,15 +111,16 @@ class CCryptoControl return m_KmSecret.len > 0; } -private: -#ifdef SRT_ENABLE_ENCRYPTION - /// Regenerate cryptographic key material. + int getCryptoMode() const + { + return m_iCryptoMode; + } + + /// Regenerate cryptographic key material if needed. /// @param[in] sock If not null, the socket will be used to send the KM message to the peer (e.g. KM refresh). /// @param[in] bidirectional If true, the key material will be regenerated for both directions (receiver and sender). + SRT_ATTR_EXCLUDES(m_mtxLock) void regenCryptoKm(CUDT* sock, bool bidirectional); -#endif - -public: size_t KeyLen() { return m_iSndKmKeyLen; } @@ -205,13 +208,17 @@ class CCryptoControl std::string FormatKmMessage(std::string hdr, int cmd, size_t srtlen); bool init(HandshakeSide, const CSrtConfig&, bool); + SRT_ATTR_EXCLUDES(m_mtxLock) void close(); - /// @return True if the handshake is in progress. + /// (Re)send KM request to a peer on timeout. /// This function is used in: - /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake) - /// - case of key regeneration, which should be then exchanged again. - void sendKeysToPeer(CUDT* sock, int iSRTT, Whether2RegenKm regen); + /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake). + /// - The case of key regeneration (KM refresh), when a new key has to be sent again. + /// In this case the first sending happens in regenCryptoKm(..). This function + /// retransmits the KM request by timeout if not KM response has been received. + SRT_ATTR_EXCLUDES(m_mtxLock) + void sendKeysToPeer(CUDT* sock, int iSRTT); void setCryptoSecret(const HaiCrypt_Secret& secret) { @@ -224,7 +231,7 @@ class CCryptoControl m_iRcvKmKeyLen = keylen; } - bool createCryptoCtx(size_t keylen, HaiCrypt_CryptoDir tx, HaiCrypt_Handle& rh); + bool createCryptoCtx(HaiCrypt_Handle& rh, size_t keylen, HaiCrypt_CryptoDir tx, bool bAESGCM); int getSndCryptoFlags() const { diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/epoll.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/epoll.h index 7b0d941c8..00d46ceb4 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/epoll.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/epoll.h @@ -69,8 +69,11 @@ class CUDTGroup; class CEPollDesc { +#ifdef __GNUG__ const int m_iID; // epoll ID - +#else + const int m_iID SRT_ATR_UNUSED; // epoll ID +#endif struct Wait; struct Notice: public SRT_EPOLL_EVENT diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/fec.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/fec.h index 71a6adfa7..029709475 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/fec.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/fec.h @@ -47,7 +47,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase size_t drop; //< by how much the sequence should increase to get to the next series size_t collected; //< how many packets were taken to collect the clip - Group(): base(CSeqNo::m_iMaxSeqNo), step(0), drop(0), collected(0) + Group(): base(SRT_SEQNO_NONE), step(0), drop(0), collected(0) { } @@ -87,7 +87,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase #if ENABLE_HEAVY_LOGGING std::string DisplayStats() { - if (base == CSeqNo::m_iMaxSeqNo) + if (base == SRT_SEQNO_NONE) return "UNINITIALIZED!!!"; std::ostringstream os; @@ -222,7 +222,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase void RcvRebuild(Group& g, int32_t seqno, Group::Type tp); int32_t RcvGetLossSeqHoriz(Group& g); int32_t RcvGetLossSeqVert(Group& g); - void EmergencyShrink(size_t n_series); + bool CheckEmergencyShrink(size_t n_series, size_t size_in_packets); static void TranslateLossRecords(const std::set& loss, loss_seqs_t& irrecover); void RcvCheckDismissColumn(int32_t seqno, int colgx, loss_seqs_t& irrecover); diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/group.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/group.h index 1bd84aeda..c2863b44e 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/group.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/group.h @@ -155,7 +155,7 @@ class CUDTGroup srt::sync::ScopedLock g(m_GroupLock); bool empty = false; - HLOGC(gmlog.Debug, log << "group/remove: going to remove @" << id << " from $" << m_GroupID); + LOGC(gmlog.Note, log << "group/remove: removing member @" << id << " from group $" << m_GroupID); gli_t f = std::find_if(m_Group.begin(), m_Group.end(), HaveID(id)); if (f != m_Group.end()) @@ -194,9 +194,6 @@ class CUDTGroup m_bConnected = false; } - // XXX BUGFIX - m_Positions.erase(id); - return !empty; } @@ -265,7 +262,7 @@ class CUDTGroup /// @param[in] pktseq Packet sequence number currently tried to be sent /// @param[out] w_u CUDT unit of the current member (to allow calling overrideSndSeqNo) /// @param[out] w_curseq Group's current sequence number (either -1 or the value used already for other links) - /// @param[out] w_final_stat w_final_stat = send_status if sending succeded. + /// @param[out] w_final_stat w_final_stat = send_status if sending succeeded. /// /// @returns true if the sending operation result (submitted in stat) is a success, false otherwise. bool sendBackup_CheckSendStatus(const time_point& currtime, @@ -406,7 +403,9 @@ class CUDTGroup SRTSOCKET m_PeerGroupID; struct GroupContainer { - std::list m_List; + private: + std::list m_List; + sync::atomic m_SizeCache; /// This field is used only by some types of groups that need /// to keep track as to which link was lately used. Note that @@ -414,8 +413,11 @@ class CUDTGroup /// must be appropriately reset. gli_t m_LastActiveLink; + public: + GroupContainer() - : m_LastActiveLink(m_List.end()) + : m_SizeCache(0) + , m_LastActiveLink(m_List.end()) { } @@ -425,18 +427,18 @@ class CUDTGroup gli_t begin() { return m_List.begin(); } gli_t end() { return m_List.end(); } bool empty() { return m_List.empty(); } - void push_back(const SocketData& data) { m_List.push_back(data); } + void push_back(const SocketData& data) { m_List.push_back(data); ++m_SizeCache; } void clear() { m_LastActiveLink = end(); m_List.clear(); + m_SizeCache = 0; } - size_t size() { return m_List.size(); } + size_t size() { return m_SizeCache; } void erase(gli_t it); }; GroupContainer m_Group; - const bool m_bSyncOnMsgNo; // It goes into a dedicated HS field. Could be true for balancing groups (not implemented). SRT_GROUP_TYPE m_type; CUDTSocket* m_listener; // A "group" can only have one listener. srt::sync::atomic m_iBusy; @@ -641,20 +643,6 @@ class CUDTGroup time_point m_tsStartTime; time_point m_tsRcvPeerStartTime; - struct ReadPos - { - std::vector packet; - SRT_MSGCTRL mctrl; - ReadPos(int32_t s) - : mctrl(srt_msgctrl_default) - { - mctrl.pktseq = s; - } - }; - std::map m_Positions; - - ReadPos* checkPacketAhead(); - void recv_CollectAliveAndBroken(std::vector& w_alive, std::set& w_broken); /// The function polls alive member sockets and retrieves a list of read-ready. @@ -813,7 +801,6 @@ class CUDTGroup SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int32_t, currentSchedSequence, m_iLastSchedSeqNo); SRTU_PROPERTY_RRW(std::set&, epollset, m_sPollID); SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int64_t, latency, m_iTsbPdDelay_us); - SRTU_PROPERTY_RO(bool, synconmsgno, m_bSyncOnMsgNo); SRTU_PROPERTY_RO(bool, closing, m_bClosing); }; diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/list.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/list.h index 03f05e927..8f921c698 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/list.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/list.h @@ -53,6 +53,8 @@ modified by #ifndef INC_SRT_LIST_H #define INC_SRT_LIST_H +#include + #include "udt.h" #include "common.h" @@ -84,6 +86,12 @@ class CSndLossList void traceState() const; + // Debug/unittest support. + + int head() const { return m_iHead; } + int next(int loc) const { return m_caSeq[loc].inext; } + int last() const { return m_iLastInsertPos; } + private: struct Seq { @@ -118,6 +126,8 @@ class CSndLossList /// @param seqno2 last sequence number in range (SRT_SEQNO_NONE if no range) bool updateElement(int pos, int32_t seqno1, int32_t seqno2); + static const int LOC_NONE = -1; + private: CSndLossList(const CSndLossList&); CSndLossList& operator=(const CSndLossList&); @@ -134,8 +144,8 @@ class CRcvLossList /// Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. /// @param [in] seqno1 sequence number starts. /// @param [in] seqno2 seqeunce number ends. - - void insert(int32_t seqno1, int32_t seqno2); + /// @return length of the loss record inserted (seqlen(seqno1, seqno2)), -1 on error. + int insert(int32_t seqno1, int32_t seqno2); /// Remove a loss seq. no. from the receiver's loss list. /// @param [in] seqno sequence number. @@ -150,6 +160,12 @@ class CRcvLossList bool remove(int32_t seqno1, int32_t seqno2); + + /// Remove all numbers that precede the given sequence number. + /// @param [in] seqno sequence number. + /// @return the first removed sequence number + int32_t removeUpTo(int32_t seqno); + /// Find if there is any lost packets whose sequence number falling seqno1 and seqno2. /// @param [in] seqno1 start sequence number. /// @param [in] seqno2 end sequence number. @@ -264,6 +280,8 @@ struct CRcvFreshLoss Emod revoke(int32_t sequence); Emod revoke(int32_t lo, int32_t hi); + + static bool removeOne(std::deque& w_container, int32_t sequence, int* had_ttl = NULL); }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/logging.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/logging.h index e79785b46..e90ad4ac2 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/logging.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/logging.h @@ -60,6 +60,7 @@ written by // LOGF uses printf-like style formatting. // Usage: LOGF(gglog.Debug, "%s: %d", param1.c_str(), int(param2)); +// NOTE: LOGF is deprecated and should not be used #define LOGF(logdes, ...) if (logdes.CheckEnabled()) logdes().setloc(__FILE__, __LINE__, __FUNCTION__).form(__VA_ARGS__) // LOGP is C++11 only OR with only one string argument. @@ -165,14 +166,24 @@ struct SRT_API LogDispatcher // See Logger::Logger; we know this has normally 2 characters, // except !!FATAL!!, which has 9. Still less than 32. - strcpy(prefix, your_pfx); - // If the size of the FA name together with severity exceeds the size, // just skip the former. if (logger_pfx && strlen(prefix) + strlen(logger_pfx) + 1 < MAX_PREFIX_SIZE) { - strcat(prefix, ":"); - strcat(prefix, logger_pfx); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(prefix, MAX_PREFIX_SIZE, "%s:%s", your_pfx, logger_pfx); +#else + snprintf(prefix, MAX_PREFIX_SIZE + 1, "%s:%s", your_pfx, logger_pfx); +#endif + } + else + { +#ifdef _MSC_VER + strncpy_s(prefix, MAX_PREFIX_SIZE + 1, your_pfx, _TRUNCATE); +#else + strncpy(prefix, your_pfx, MAX_PREFIX_SIZE); + prefix[MAX_PREFIX_SIZE] = '\0'; +#endif } } @@ -242,7 +253,9 @@ struct SRT_API LogDispatcher return *this; } - DummyProxy& form(const char*, ...) + // DEPRECATED: DO NOT use LOGF/HLOGF macros anymore. + // Use iostream-style formatting with LOGC or a direct argument with LOGP. + SRT_ATR_DEPRECATED_PX DummyProxy& form(const char*, ...) SRT_ATR_DEPRECATED { return *this; } @@ -356,7 +369,11 @@ struct LogDispatcher::Proxy { char buf[512]; - vsprintf(buf, fmts, ap); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _vsnprintf(buf, sizeof(buf) - 1, fmts, ap); +#else + vsnprintf(buf, sizeof(buf), fmts, ap); +#endif size_t len = strlen(buf); if ( buf[len-1] == '\n' ) { diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/md5.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/md5.h index 98bd07665..643981c01 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/md5.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/md5.h @@ -27,7 +27,7 @@ This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at - http://www.ietf.org/rfc/rfc1321.txt + http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being @@ -38,23 +38,24 @@ that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . + added conditionalization for C++ compilation from Martin + Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED -# define md5_INCLUDED +#define md5_INCLUDED /* * All symbols have been put under the srt namespace * to avoid potential linkage conflicts. */ -namespace srt { +namespace srt +{ /* * This package supports both compile-time and run-time determination of CPU @@ -67,23 +68,24 @@ namespace srt { */ typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; /* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); +void md5_init(md5_state_t* pms); /* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +void md5_append(md5_state_t* pms, const md5_byte_t* data, int nbytes); /* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +void md5_finish(md5_state_t* pms, md5_byte_t digest[16]); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/netinet_any.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/netinet_any.h new file mode 100644 index 000000000..a38765c08 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/netinet_any.h @@ -0,0 +1,426 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_NETINET_ANY_H +#define INC_SRT_NETINET_ANY_H + +#include // memcmp +#include +#include +#include "platform_sys.h" + +// This structure should replace every use of sockaddr and its currently +// used specializations, sockaddr_in and sockaddr_in6. This is to simplify +// the use of the original BSD API that relies on type-violating type casts. +// You can use the instances of sockaddr_any in every place where sockaddr is +// required. + +namespace srt +{ + +struct sockaddr_any +{ + union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + }; + + // The type is intended to be the same as the length + // parameter in ::accept, ::bind and ::connect functions. + + // This is the type used by SRT. + typedef int len_t; + + // This is the type used by system functions +#ifdef _WIN32 + typedef int syslen_t; +#else + typedef socklen_t syslen_t; +#endif + + // Note: by having `len_t` type here the usage in + // API functions is here limited to SRT. For system + // functions you can pass the address here as (socklen_t*)&sa.len, + // but just do it on your own risk, as there's no guarantee + // that sizes of `int` and `socklen_t` do not differ. The safest + // way seems to be using an intermediate proxy to be written + // back here from the value of `syslen_t`. + len_t len; + + struct SysLenWrapper + { + syslen_t syslen; + len_t& backwriter; + syslen_t* operator&() { return &syslen; } + + SysLenWrapper(len_t& source): syslen(source), backwriter(source) + { + } + + ~SysLenWrapper() + { + backwriter = syslen; + } + }; + + // Usage: + // ::accept(lsn_sock, sa.get(), &sa.syslen()); + SysLenWrapper syslen() + { + return SysLenWrapper(len); + } + + static size_t storage_size() + { + typedef union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + } ucopy; + return sizeof (ucopy); + } + + void reset() + { + // sin6 is the largest field + memset((&sin6), 0, sizeof sin6); + len = 0; + } + + // Default domain is unspecified, and + // in this case the size is 0. + // Note that AF_* (and alias PF_*) types have + // many various values, of which only + // AF_INET and AF_INET6 are handled here. + // Others make the same effect as unspecified. + explicit sockaddr_any(int domain = AF_UNSPEC) + { + // Default domain is "unspecified", 0 + reset(); + + // Overriding family as required in the parameters + // and the size then accordingly. + sa.sa_family = domain == AF_INET || domain == AF_INET6 ? domain : AF_UNSPEC; + switch (domain) + { + case AF_INET: + len = len_t(sizeof (sockaddr_in)); + break; + + // Use size of sin6 as the default size + // len must be properly set so that the + // family-less sockaddr is passed to bind/accept + default: + len = len_t(sizeof (sockaddr_in6)); + break; + } + } + + sockaddr_any(const sockaddr_storage& stor) + { + // Here the length isn't passed, so just rely on family. + set((const sockaddr*)&stor); + } + + sockaddr_any(const sockaddr* source, len_t namelen = 0) + { + if (namelen == 0) + set(source); + else + set(source, namelen); + } + + void set(const sockaddr* source) + { + // Less safe version, simply trust the caller that the + // memory at 'source' is also large enough to contain + // all data required for particular family. + if (source->sa_family == AF_INET) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6) + { + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + // Error fallback: no other families than IP are regarded. + // Note: socket set up this way isn't intended to be used + // for bind/accept. + sa.sa_family = AF_UNSPEC; + len = 0; + } + } + + void set(const sockaddr* source, syslen_t namelen) + { + // It's not safe to copy it directly, so check. + if (source->sa_family == AF_INET && namelen >= syslen_t(sizeof sin)) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6 && namelen >= syslen_t(sizeof sin6)) + { + // Note: this isn't too safe, may crash for stupid values + // of source->sa_family or any other data + // in the source structure, so make sure it's correct first. + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + reset(); + } + } + + void set(const sockaddr_in& in4) + { + memcpy((&sin), &in4, sizeof in4); + len = sizeof in4; + } + + void set(const sockaddr_in6& in6) + { + memcpy((&sin6), &in6, sizeof in6); + len = sizeof in6; + } + + sockaddr_any(const in_addr& i4_adr, uint16_t port) + { + // Some cases require separately IPv4 address passed as in_addr, + // so port is given separately. + sa.sa_family = AF_INET; + sin.sin_addr = i4_adr; + sin.sin_port = htons(port); + len = sizeof sin; + } + + sockaddr_any(const in6_addr& i6_adr, uint16_t port) + { + sa.sa_family = AF_INET6; + sin6.sin6_addr = i6_adr; + sin6.sin6_port = htons(port); + len = sizeof sin6; + } + + static len_t size(int family) + { + switch (family) + { + case AF_INET: + return len_t(sizeof (sockaddr_in)); + + case AF_INET6: + return len_t(sizeof (sockaddr_in6)); + + default: + return 0; // fallback + } + } + + bool empty() const + { + bool isempty = true; // unspec-family address is always empty + + if (sa.sa_family == AF_INET) + { + isempty = (sin.sin_port == 0 + && sin.sin_addr.s_addr == 0); + } + else if (sa.sa_family == AF_INET6) + { + isempty = (sin6.sin6_port == 0 + && memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0); + } + // otherwise isempty stays with default false + return isempty; + } + + len_t size() const + { + return size(sa.sa_family); + } + + int family() const { return sa.sa_family; } + void family(int val) + { + sa.sa_family = val; + len = size(); + } + + // port is in exactly the same location in both sin and sin6 + // and has the same size. This is actually yet another common + // field, just not mentioned in the sockaddr structure. + uint16_t& r_port() { return sin.sin_port; } + uint16_t r_port() const { return sin.sin_port; } + int hport() const { return ntohs(sin.sin_port); } + + void hport(int value) + { + // Port is fortunately located at the same position + // in both sockaddr_in and sockaddr_in6 and has the + // same size. + sin.sin_port = htons(value); + } + + sockaddr* get() { return &sa; } + const sockaddr* get() const { return &sa; } + + // Sometimes you need to get the address + // the way suitable for e.g. inet_ntop. + const void* get_addr() const + { + if (sa.sa_family == AF_INET) + return &sin.sin_addr.s_addr; + + if (sa.sa_family == AF_INET6) + return &sin6.sin6_addr; + + return NULL; + } + + void* get_addr() + { + const sockaddr_any* that = this; + return (void*)that->get_addr(); + } + + template struct TypeMap; + + template + typename TypeMap::type& get(); + + struct Equal + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if (c1.family() != c2.family()) + return false; + + // Cannot use memcmp due to having in some systems + // another field like sockaddr_in::sin_len. This exists + // in some BSD-derived systems, but is not required by POSIX. + // Therefore sockaddr_any class cannot operate with it, + // as in this situation it would be safest to state that + // particular implementations may have additional fields + // of different purpose beside those required by POSIX. + // + // The only reliable way to compare two underlying sockaddr + // object is then to compare the port value and the address + // value. + // + // Fortunately the port is 16-bit and located at the same + // offset in both sockaddr_in and sockaddr_in6. + + return c1.sin.sin_port == c2.sin.sin_port + && c1.equal_address(c2); + } + }; + + struct EqualAddress + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if ( c1.sa.sa_family == AF_INET ) + { + return c1.sin.sin_addr.s_addr == c2.sin.sin_addr.s_addr; + } + + if ( c1.sa.sa_family == AF_INET6 ) + { + return memcmp(&c1.sin6.sin6_addr, &c2.sin6.sin6_addr, sizeof (in6_addr)) == 0; + } + + return false; + } + + }; + + bool equal_address(const sockaddr_any& rhs) const + { + return EqualAddress()(*this, rhs); + } + + struct Less + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + return memcmp(&c1, &c2, sizeof(c1)) < 0; + } + }; + + // Tests if the current address is the "any" wildcard. + bool isany() const + { + if (sa.sa_family == AF_INET) + return sin.sin_addr.s_addr == INADDR_ANY; + + if (sa.sa_family == AF_INET6) + return memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0; + + return false; + } + + // Debug support + std::string str() const + { + if (family() != AF_INET && family() != AF_INET6) + return "unknown:0"; + + std::ostringstream output; + char hostbuf[1024]; + int flags; + + #if ENABLE_GETNAMEINFO + flags = NI_NAMEREQD; + #else + flags = NI_NUMERICHOST | NI_NUMERICSERV; + #endif + + if (!getnameinfo(get(), size(), hostbuf, 1024, NULL, 0, flags)) + { + output << hostbuf; + } + + output << ":" << hport(); + return output.str(); + } + + bool operator==(const sockaddr_any& other) const + { + return Equal()(*this, other); + } + + bool operator!=(const sockaddr_any& other) const { return !(*this == other); } +}; + +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in type; }; +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in6 type; }; + +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin; } +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin6; } + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packet.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packet.h new file mode 100644 index 000000000..027d5f0b3 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packet.h @@ -0,0 +1,397 @@ +/* + * SRT - Secure Reliable Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/02/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_PACKET_H +#define INC_SRT_PACKET_H + +#include "udt.h" +#include "common.h" +#include "utilities.h" +#include "netinet_any.h" +#include "packetfilter_api.h" + +namespace srt +{ + +////////////////////////////////////////////////////////////////////////////// +// The purpose of the IOVector class is to proide a platform-independet interface +// to the WSABUF on Windows and iovec on Linux, that can be easilly converted +// to the native structure for use in WSARecvFrom() and recvmsg(...) functions +class IOVector +#ifdef _WIN32 + : public WSABUF +#else + : public iovec +#endif +{ +public: + inline void set(void* buffer, size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; + buf = (CHAR*)buffer; +#else + iov_base = (void*)buffer; + iov_len = length; +#endif + } + + inline char*& dataRef() + { +#ifdef _WIN32 + return buf; +#else + return (char*&)iov_base; +#endif + } + + inline char* data() + { +#ifdef _WIN32 + return buf; +#else + return (char*)iov_base; +#endif + } + + inline size_t size() const + { +#ifdef _WIN32 + return (size_t)len; +#else + return iov_len; +#endif + } + + inline void setLength(size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; +#else + iov_len = length; +#endif + } +}; + +/// To define packets in order in the buffer. This is public due to being used in buffer. +enum PacketBoundary +{ + PB_SUBSEQUENT = 0, // 00: a packet in the middle of a message, neither the first, not the last. + PB_LAST = 1, // 01: last packet of a message + PB_FIRST = 2, // 10: first packet of a message + PB_SOLO = 3, // 11: solo message packet +}; + +// Breakdown of the PM_SEQNO field in the header: +// C| X X ... X, where: +typedef Bits<31> SEQNO_CONTROL; +// 1|T T T T T T T T T T T T T T T|E E...E +typedef Bits<30, 16> SEQNO_MSGTYPE; +typedef Bits<15, 0> SEQNO_EXTTYPE; +// 0|S S ... S +typedef Bits<30, 0> SEQNO_VALUE; + +// This bit cannot be used by SEQNO anyway, so it's additionally used +// in LOSSREPORT data specification to define that this value is the +// BEGIN value for a SEQNO range (to distinguish it from a SOLO loss SEQNO value). +const int32_t LOSSDATA_SEQNO_RANGE_FIRST = SEQNO_CONTROL::mask; + +// Just cosmetics for readability. +const int32_t LOSSDATA_SEQNO_RANGE_LAST = 0, LOSSDATA_SEQNO_SOLO = 0; + +inline int32_t CreateControlSeqNo(UDTMessageType type) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(uint32_t(type)); +} + +inline int32_t CreateControlExtSeqNo(int exttype) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(size_t(UMSG_EXT)) | SEQNO_EXTTYPE::wrap(exttype); +} + +// MSGNO breakdown: B B|O|K K|R|M M M M M M M M M M...M +typedef Bits<31, 30> MSGNO_PACKET_BOUNDARY; +typedef Bits<29> MSGNO_PACKET_INORDER; +typedef Bits<28, 27> MSGNO_ENCKEYSPEC; +#if 1 // can block rexmit flag +// New bit breakdown - rexmit flag supported. +typedef Bits<26> MSGNO_REXMIT; +typedef Bits<25, 0> MSGNO_SEQ; +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ_OLD; +// This symbol is for older SRT version, where the peer does not support the MSGNO_REXMIT flag. +// The message should be extracted as PMASK_MSGNO_SEQ, if REXMIT is supported, and PMASK_MSGNO_SEQ_OLD otherwise. + +const uint32_t PACKET_SND_NORMAL = 0, PACKET_SND_REXMIT = MSGNO_REXMIT::mask; +const int MSGNO_SEQ_MAX = MSGNO_SEQ::mask; + +#else +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ; +#endif + +typedef RollNumber MsgNo; + +// constexpr in C++11 ! +inline int32_t PacketBoundaryBits(PacketBoundary o) +{ + return MSGNO_PACKET_BOUNDARY::wrap(int32_t(o)); +} + +enum EncryptionKeySpec +{ + EK_NOENC = 0, + EK_EVEN = 1, + EK_ODD = 2 +}; + +enum EncryptionStatus +{ + ENCS_CLEAR = 0, + ENCS_FAILED = -1, + ENCS_NOTSUP = -2 +}; + +const int32_t PMASK_MSGNO_ENCKEYSPEC = MSGNO_ENCKEYSPEC::mask; +inline int32_t EncryptionKeyBits(EncryptionKeySpec f) +{ + return MSGNO_ENCKEYSPEC::wrap(int32_t(f)); +} +inline EncryptionKeySpec GetEncryptionKeySpec(int32_t msgno) +{ + return EncryptionKeySpec(MSGNO_ENCKEYSPEC::unwrap(msgno)); +} + +const int32_t PUMASK_SEQNO_PROBE = 0xF; + +std::string PacketMessageFlagStr(uint32_t msgno_field); + +class CPacket +{ + friend class CChannel; + friend class CSndQueue; + friend class CRcvQueue; + +public: + CPacket(); + ~CPacket(); + + void allocate(size_t size); + void deallocate(); + + /// Get the payload or the control information field length. + /// @return the payload or the control information field length. + size_t getLength() const; + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + void setLength(size_t len); + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + /// @param cap [in] capacity (if known). + void setLength(size_t len, size_t cap); + + /// Pack a Control packet. + /// @param pkttype [in] packet type filed. + /// @param lparam [in] pointer to the first data structure, explained by the packet type. + /// @param rparam [in] pointer to the second data structure, explained by the packet type. + /// @param size [in] size of rparam, in number of bytes; + void pack(UDTMessageType pkttype, const int32_t* lparam = NULL, void* rparam = NULL, size_t size = 0); + + /// Read the packet vector. + /// @return Pointer to the packet vector. + IOVector* getPacketVector(); + + uint32_t* getHeader() { return m_nHeader; } + + /// Read the packet type. + /// @return packet type filed (000 ~ 111). + UDTMessageType getType() const; + + bool isControl(UDTMessageType type) const { return isControl() && type == getType(); } + + bool isControl() const { return 0 != SEQNO_CONTROL::unwrap(m_nHeader[SRT_PH_SEQNO]); } + + void setControl(UDTMessageType type) { m_nHeader[SRT_PH_SEQNO] = SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(type); } + + /// Read the extended packet type. + /// @return extended packet type filed (0x000 ~ 0xFFF). + int getExtendedType() const; + + /// Read the ACK-2 seq. no. + /// @return packet header field (bit 16~31). + int32_t getAckSeqNo() const; + + uint16_t getControlFlags() const; + + // Note: this will return a "singular" value, if the packet + // contains the control message + int32_t getSeqNo() const { return m_nHeader[SRT_PH_SEQNO]; } + + /// Read the message boundary flag bit. + /// @return packet header field [1] (bit 0~1). + PacketBoundary getMsgBoundary() const; + + /// Read the message inorder delivery flag bit. + /// @return packet header field [1] (bit 2). + bool getMsgOrderFlag() const; + + /// Read the rexmit flag (true if the packet was sent due to retransmission). + /// If the peer does not support retransmission flag, the current agent cannot use it as well + /// (because the peer will understand this bit as a part of MSGNO field). + bool getRexmitFlag() const; + + void setRexmitFlag(bool bRexmit); + + /// Read the message sequence number. + /// @return packet header field [1] + int32_t getMsgSeq(bool has_rexmit = true) const; + + /// Read the message crypto key bits. + /// @return packet header field [1] (bit 3~4). + EncryptionKeySpec getMsgCryptoFlags() const; + + void setMsgCryptoFlags(EncryptionKeySpec spec); + + /// Read the message time stamp. + /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). + uint32_t getMsgTimeStamp() const; + + sockaddr_any udpDestAddr() const { return m_DestAddr; } + +#ifdef SRT_DEBUG_TSBPD_WRAP // Receiver + static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; // 27 bit fast wraparound for tests (~2m15s) +#else + static const uint32_t MAX_TIMESTAMP = 0xFFFFFFFF; // Full 32 bit (01h11m35s) +#endif + +protected: + static const uint32_t TIMESTAMP_MASK = MAX_TIMESTAMP; // this value to be also used as a mask +public: + /// Clone this packet. + /// @return Pointer to the new packet. + CPacket* clone() const; + + enum PacketVectorFields + { + PV_HEADER = 0, + PV_DATA = 1, + + PV_SIZE = 2 + }; + +public: + void toNL(); + void toHL(); + +protected: + // DynamicStruct is the same as array of given type and size, just it + // enforces that you index it using a symbol from symbolic enum type, not by a bare integer. + typedef DynamicStruct HEADER_TYPE; + HEADER_TYPE m_nHeader; //< The 128-bit header field + + IOVector m_PacketVector[PV_SIZE]; //< The two-dimensional vector of an SRT packet [header, data] + + int32_t m_extra_pad; + bool m_data_owned; + sockaddr_any m_DestAddr; + size_t m_zCapacity; + +protected: + CPacket& operator=(const CPacket&); + CPacket(const CPacket&); + +public: + int32_t& m_iSeqNo; // alias: sequence number + int32_t& m_iMsgNo; // alias: message number + int32_t& m_iTimeStamp; // alias: timestamp + int32_t& m_iID; // alias: destination SRT socket ID + char*& m_pcData; // alias: payload (data packet) / control information fields (control packet) + + // Experimental: sometimes these references don't work! + char* getData(); + char* release(); + + static const size_t HDR_SIZE = sizeof(HEADER_TYPE); // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t) + + // Can also be calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr). + static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }. + + static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE; + + // Maximum transmission unit size. 1500 in case of Ethernet II (RFC 1191). + static const size_t ETH_MAX_MTU_SIZE = 1500; + + // Maximum payload size of an SRT packet. + static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE; + + // Packet interface + char* data() { return m_pcData; } + const char* data() const { return m_pcData; } + size_t size() const { return getLength(); } + size_t capacity() const { return m_zCapacity; } + void setCapacity(size_t cap) { m_zCapacity = cap; } + uint32_t header(SrtPktHeaderFields field) const { return m_nHeader[field]; } + +#if ENABLE_LOGGING + std::string MessageFlagStr() { return PacketMessageFlagStr(m_nHeader[SRT_PH_MSGNO]); } + std::string Info(); +#else + std::string MessageFlagStr() { return std::string(); } + std::string Info() { return std::string(); } +#endif +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter.h new file mode 100644 index 000000000..429e81e79 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter.h @@ -0,0 +1,219 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_H +#define INC_SRT_PACKETFILTER_H + +#include +#include +#include + +#include "packet.h" +#include "utilities.h" +#include "packetfilter_api.h" + +namespace srt { + +class CUnitQueue; +struct CUnit; +class CUDT; + +class PacketFilter +{ + friend class SrtPacketFilterBase; + +public: + typedef std::vector< std::pair > loss_seqs_t; + + typedef SrtPacketFilterBase* filter_create_t(const SrtFilterInitializer& init, std::vector&, const std::string& config); + + class Factory + { + public: + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, std::vector& provided, const std::string& confstr) = 0; + + // Characteristic data + virtual size_t ExtraSize() const = 0; + + // Represent default parameters. This is for completing and comparing + // filter configurations from both parties. Possible values to return: + // - an empty string (all parameters are mandatory) + // - a form of: ",:,..." + virtual std::string defaultConfig() const = 0; + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const = 0; + virtual ~Factory(); + }; +private: + friend bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + + template + class Creator: public Factory + { + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, + std::vector& provided, + const std::string& confstr) ATR_OVERRIDE + { return new Target(init, provided, confstr); } + + // Import the extra size data + virtual size_t ExtraSize() const ATR_OVERRIDE { return Target::EXTRA_SIZE; } + virtual std::string defaultConfig() const ATR_OVERRIDE { return Target::defaultConfig; } + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const ATR_OVERRIDE + { + return Target::verifyConfig(config, (w_errormsg)); + } + + public: + Creator() {} + virtual ~Creator() {} + }; + + + // We need a private wrapper for the auto-pointer, can't use + // std::unique_ptr here due to no C++11. + struct ManagedPtr + { + Factory* f; + mutable bool owns; + + // Accept whatever + ManagedPtr(Factory* ff): f(ff), owns(true) {} + ManagedPtr(): f(NULL), owns(false) {} + ~ManagedPtr() + { + if (owns) + delete f; + } + + void copy_internal(const ManagedPtr& other) + { + other.owns = false; + f = other.f; + owns = true; + } + + ManagedPtr(const ManagedPtr& other) + { + copy_internal(other); + } + + void operator=(const ManagedPtr& other) + { + if (owns) + delete f; + copy_internal(other); + } + + Factory* operator->() { return f; } + Factory* get() { return f; } + }; + + // The list of builtin names that are reserved. + static std::set builtin_filters; + + // Temporarily changed to linear searching, until this is exposed + // for a user-defined filter. + typedef std::map filters_map_t; + static filters_map_t filters; + + // This is a filter container. + SrtPacketFilterBase* m_filter; + void Check() + { +#if ENABLE_DEBUG + if (!m_filter) + abort(); +#endif + // Don't do any check for now. + } + +public: + + static void globalInit(); + + static bool IsBuiltin(const std::string&); + + template + static bool add(const std::string& name) + { + if (IsBuiltin(name)) + return false; + + filters[name] = new Creator; + return true; + } + + static Factory* find(const std::string& type) + { + filters_map_t::iterator i = filters.find(type); + if (i == filters.end()) + return NULL; // No matter what to return - this is "undefined behavior" to be prevented + return i->second.get(); + } + + // Filter is optional, so this check should be done always + // manually. + bool installed() const { return m_filter; } + operator bool() const { return installed(); } + + SrtPacketFilterBase* operator->() { Check(); return m_filter; } + + // In the beginning it's initialized as first, builtin default. + // Still, it will be created only when requested. + PacketFilter(): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // Copy constructor - important when listener-spawning + // Things being done: + // 1. The filter is individual, so don't copy it. Set NULL. + // 2. This will be configued anyway basing on possibly a new rule set. + PacketFilter(const PacketFilter& source SRT_ATR_UNUSED): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // This function will be called by the parent CUDT + // in appropriate time. It should select appropriate + // filter basing on the value in selector, then + // pin oneself in into CUDT for receiving event signals. + bool configure(CUDT* parent, CUnitQueue* uq, const std::string& confstr); + + static bool correctConfig(const SrtFilterConfig& c); + + // Will delete the pinned in filter object. + // This must be defined in *.cpp file due to virtual + // destruction. + ~PacketFilter(); + + // Simple wrappers + void feedSource(CPacket& w_packet); + SRT_ARQLevel arqLevel(); + bool packControlPacket(int32_t seq, int kflg, CPacket& w_packet); + void receive(CUnit* unit, std::vector& w_incoming, loss_seqs_t& w_loss_seqs); + +protected: + PacketFilter& operator=(const PacketFilter& p); + void InsertRebuilt(std::vector& incoming, CUnitQueue* uq); + + CUDT* m_parent; + + // Sender part + SrtPacket m_sndctlpkt; + + // Receiver part + CUnitQueue* m_unitq; + std::vector m_provided; +}; + +bool CheckFilterCompat(SrtFilterConfig& w_agent, SrtFilterConfig peer); + +inline void PacketFilter::feedSource(CPacket& w_packet) { SRT_ASSERT(m_filter); return m_filter->feedSource((w_packet)); } +inline SRT_ARQLevel PacketFilter::arqLevel() { SRT_ASSERT(m_filter); return m_filter->arqLevel(); } + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_api.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_api.h new file mode 100644 index 000000000..3bfba7c76 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_api.h @@ -0,0 +1,158 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_API_H +#define INC_SRT_PACKETFILTER_API_H + +#include "platform_sys.h" + +#include +#include +#include +#include +#include + +namespace srt { + +class CPacket; + +enum SrtPktHeaderFields +{ + SRT_PH_SEQNO = 0, //< sequence number + SRT_PH_MSGNO = 1, //< message number + SRT_PH_TIMESTAMP = 2, //< time stamp + SRT_PH_ID = 3, //< socket ID + + // Must be the last value - this is size of all, not a field id + SRT_PH_E_SIZE +}; + + +enum SRT_ARQLevel +{ + SRT_ARQ_NEVER, //< Never send LOSSREPORT + SRT_ARQ_ONREQ, //< Only record the loss, but report only those that are returned in receive() + SRT_ARQ_ALWAYS, //< always send LOSSREPORT immediately after detecting a loss +}; + +struct SrtConfig +{ + std::string type; + typedef std::map par_t; + par_t parameters; +}; + +struct SrtFilterConfig: SrtConfig +{ + size_t extra_size; // needed for filter option check against payload size +}; + +struct SrtFilterInitializer +{ + SRTSOCKET socket_id; + int32_t snd_isn; + int32_t rcv_isn; + size_t payload_size; + size_t rcvbuf_size; +}; + +struct SrtPacket +{ + uint32_t hdr[SRT_PH_E_SIZE]; + char buffer[SRT_LIVE_MAX_PLSIZE]; + size_t length; + + SrtPacket(size_t size): length(size) + { + memset(hdr, 0, sizeof(hdr)); + } + + uint32_t header(SrtPktHeaderFields field) { return hdr[field]; } + char* data() { return buffer; } + const char* data() const { return buffer; } + size_t size() const { return length; } +}; + + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& w_config); + + +class SrtPacketFilterBase +{ + SrtFilterInitializer initParams; + +protected: + + SRTSOCKET socketID() const { return initParams.socket_id; } + int32_t sndISN() const { return initParams.snd_isn; } + int32_t rcvISN() const { return initParams.rcv_isn; } + size_t payloadSize() const { return initParams.payload_size; } + size_t rcvBufferSize() const { return initParams.rcvbuf_size; } + + friend class PacketFilter; + + // Beside the size of the rows, special values: + // 0: if you have 0 specified for rows, there are only columns + // -1: Only during the handshake, use the value specified by peer. + // -N: The N value still specifies the size, but in particular + // dimension there is no filter control packet formed nor expected. + +public: + + typedef std::vector< std::pair > loss_seqs_t; + +protected: + + SrtPacketFilterBase(const SrtFilterInitializer& i): initParams(i) + { + } + + // Sender side + + /// This function creates and stores the filter control packet with + /// a prediction to be immediately sent. This is called in the function + /// that normally is prepared for extracting a data packet from the sender + /// buffer and send it over the channel. The returned value informs the + /// caller whether the control packet was available and therefore provided. + /// @param [OUT] packet Target place where the packet should be stored + /// @param [IN] seq Sequence number of the packet last requested for sending + /// @return true if the control packet has been provided + virtual bool packControlPacket(SrtPacket& packet, int32_t seq) = 0; + + /// This is called at the moment when the sender queue decided to pick up + /// a new packet from the scheduled packets. This should be then used to + /// continue filling the group, possibly followed by final calculating the + /// control packet ready to send. The packet received by this function is + /// potentially allowed to be modified. + /// @param [INOUT] packet The packet about to send + virtual void feedSource(CPacket& packet) = 0; + + + // Receiver side + + // This function is called at the moment when a new data packet has + // arrived (no matter if subsequent or recovered). The 'state' value + // defines the configured level of loss state required to send the + // loss report. + virtual bool receive(const CPacket& pkt, loss_seqs_t& loss_seqs) = 0; + + // Backward configuration. + // This should have some stable value after the configuration is parsed, + // and it should be a stable value set ONCE, after the filter module is ready. + virtual SRT_ARQLevel arqLevel() = 0; + + virtual ~SrtPacketFilterBase() + { + } +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_builtin.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_builtin.h new file mode 100644 index 000000000..80983250a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/packetfilter_builtin.h @@ -0,0 +1,18 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +#ifndef INC_SRT_PACKETFILTER_BUILTIN_H +#define INC_SRT_PACKETFILTER_BUILTIN_H + +// Integration header +#include "fec.h" + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/platform_sys.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/platform_sys.h index fae95803f..e2f0aa4d9 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/platform_sys.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/platform_sys.h @@ -7,28 +7,113 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ -#ifndef INC__PLATFORM_SYS_H -#define INC__PLATFORM_SYS_H +#ifndef INC_SRT_PLATFORM_SYS_H +#define INC_SRT_PLATFORM_SYS_H + +// INFORMATION +// +// This file collects all required platform-specific declarations +// required to provide everything that the SRT library needs from system. +// +// There's also semi-modular system implemented using SRT_IMPORT_* macros. +// To require a module to be imported, #define SRT_IMPORT_* where * is +// the module name. Currently handled module macros: +// +// SRT_IMPORT_TIME (mach time on Mac, portability gettimeofday on WIN32) +// SRT_IMPORT_EVENT (includes kevent on Mac) + #ifdef _WIN32 #include #include #include #include + +#ifndef __MINGW32__ + #include +#endif + + #ifdef SRT_IMPORT_TIME + #include + #endif + #include #include - #if defined(_MSC_VER) - #pragma warning(disable:4251) - #endif #else + +#if defined(__APPLE__) && __APPLE__ +// Warning: please keep this test as it is, do not make it +// "#if __APPLE__" or "#ifdef __APPLE__". In applications with +// a strict "no warning policy", "#if __APPLE__" triggers an "undef" +// error. With GCC, an old & never fixed bug prevents muting this +// warning (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431). +// Before this fix, the solution was to "#define __APPLE__ 0" before +// including srt.h. So, don't use "#ifdef __APPLE__" either. + +// XXX Check if this condition doesn't require checking of +// also other macros, like TARGET_OS_IOS etc. + +#include "TargetConditionals.h" +#define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ + +#ifdef SRT_IMPORT_TIME + #include +#endif + +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif + +#endif + +#ifdef BSD +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif +#endif + +#ifdef LINUX + +#ifdef SRT_IMPORT_EVENT + #include + #include +#endif + +#endif + +#ifdef __ANDROID__ + +#ifdef SRT_IMPORT_EVENT + #include +#endif + +#endif + #include #include +#include #include #include #include #include #include -#include +#include + +#ifdef __cplusplus +// Headers for errno, string and stdlib are +// included indirectly correct C++ way. +#else +#include +#include +#include +#endif + #endif #endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/queue.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/queue.h new file mode 100644 index 000000000..dd68a7721 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/queue.h @@ -0,0 +1,603 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/12/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_QUEUE_H +#define INC_SRT_QUEUE_H + +#include "common.h" +#include "packet.h" +#include "socketconfig.h" +#include "netinet_any.h" +#include "utilities.h" +#include +#include +#include +#include + +namespace srt +{ +class CChannel; +class CUDT; + +struct CUnit +{ + CPacket m_Packet; // packet + sync::atomic m_bTaken; // true if the unit is is use (can be stored in the RCV buffer). +}; + +class CUnitQueue +{ +public: + /// @brief Construct a unit queue. + /// @param mss Initial number of units to allocate. + /// @param mss Maximum segment size meaning the size of each unit. + /// @throws CUDTException SRT_ENOBUF. + CUnitQueue(int initNumUnits, int mss); + ~CUnitQueue(); + +public: + int capacity() const { return m_iSize; } + int size() const { return m_iSize - m_iNumTaken; } + +public: + /// @brief Find an available unit for incoming packet. Allocate new units if 90% or more are in use. + /// @note This function is not thread-safe. Currently only CRcvQueue::worker thread calls it, thus + /// it is not an issue. However, must be protected if used from several threads in the future. + /// @return Pointer to the available unit, NULL if not found. + CUnit* getNextAvailUnit(); + + void makeUnitFree(CUnit* unit); + + void makeUnitTaken(CUnit* unit); + +private: + struct CQEntry + { + CUnit* m_pUnit; // unit queue + char* m_pBuffer; // data buffer + int m_iSize; // size of each queue + + CQEntry* m_pNext; + }; + + /// Increase the unit queue size (by @a m_iBlockSize units). + /// Uses m_mtx to protect access and changes of the queue state. + /// @return 0: success, -1: failure. + int increase_(); + + /// @brief Allocated a CQEntry of iNumUnits with each unit of mss bytes. + /// @param iNumUnits a number of units to allocate + /// @param mss the size of each unit in bytes. + /// @return a pointer to a newly allocated entry on success, NULL otherwise. + static CQEntry* allocateEntry(const int iNumUnits, const int mss); + +private: + CQEntry* m_pQEntry; // pointer to the first unit queue + CQEntry* m_pCurrQueue; // pointer to the current available queue + CQEntry* m_pLastQueue; // pointer to the last unit queue + CUnit* m_pAvailUnit; // recent available unit + int m_iSize; // total size of the unit queue, in number of packets + sync::atomic m_iNumTaken; // total number of valid (occupied) packets in the queue + const int m_iMSS; // unit buffer size + const int m_iBlockSize; // Number of units in each CQEntry. + +private: + CUnitQueue(const CUnitQueue&); + CUnitQueue& operator=(const CUnitQueue&); +}; + +struct CSNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; + + sync::atomic m_iHeapLoc; // location on the heap, -1 means not on the heap +}; + +class CSndUList +{ +public: + CSndUList(sync::CTimer* pTimer); + ~CSndUList(); + +public: + enum EReschedule + { + DONT_RESCHEDULE = 0, + DO_RESCHEDULE = 1 + }; + + static EReschedule rescheduleIf(bool cond) { return cond ? DO_RESCHEDULE : DONT_RESCHEDULE; } + + /// Update the timestamp of the UDT instance on the list. + /// @param [in] u pointer to the UDT instance + /// @param [in] reschedule if the timestamp should be rescheduled + /// @param [in] ts the next time to trigger sending logic on the CUDT + void update(const CUDT* u, EReschedule reschedule, sync::steady_clock::time_point ts = sync::steady_clock::now()); + + /// Retrieve the next (in time) socket from the heap to process its sending request. + /// @return a pointer to CUDT instance to process next. + CUDT* pop(); + + /// Remove UDT instance from the list. + /// @param [in] u pointer to the UDT instance + void remove(const CUDT* u);// EXCLUDES(m_ListLock); + + /// Retrieve the next scheduled processing time. + /// @return Scheduled processing time of the first UDT socket in the list. + sync::steady_clock::time_point getNextProcTime(); + + /// Wait for the list to become non empty. + void waitNonEmpty() const; + + /// Signal to stop waiting in waitNonEmpty(). + void signalInterrupt() const; + +private: + /// Doubles the size of the list. + /// + void realloc_();// REQUIRES(m_ListLock); + + /// Insert a new UDT instance into the list with realloc if required. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_(const sync::steady_clock::time_point& ts, const CUDT* u); + + /// Insert a new UDT instance into the list without realloc. + /// Should be called if there is a guaranteed space for the element. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_norealloc_(const sync::steady_clock::time_point& ts, const CUDT* u);// REQUIRES(m_ListLock); + + /// Removes CUDT entry from the list. + /// If the last entry is removed, calls sync::CTimer::interrupt(). + void remove_(const CUDT* u); + +private: + CSNode** m_pHeap; // The heap array + int m_iArrayLength; // physical length of the array + int m_iLastEntry; // position of last entry on the heap array or -1 if empty. + + mutable sync::Mutex m_ListLock; // Protects the list (m_pHeap, m_iArrayLength, m_iLastEntry). + mutable sync::Condition m_ListCond; + + sync::CTimer* const m_pTimer; + +private: + CSndUList(const CSndUList&); + CSndUList& operator=(const CSndUList&); +}; + +struct CRNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; // Time Stamp + + CRNode* m_pPrev; // previous link + CRNode* m_pNext; // next link + + sync::atomic m_bOnList; // if the node is already on the list +}; + +class CRcvUList +{ +public: + CRcvUList(); + ~CRcvUList(); + +public: + /// Insert a new UDT instance to the list. + /// @param [in] u pointer to the UDT instance + + void insert(const CUDT* u); + + /// Remove the UDT instance from the list. + /// @param [in] u pointer to the UDT instance + + void remove(const CUDT* u); + + /// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing. + /// @param [in] u pointer to the UDT instance + + void update(const CUDT* u); + +public: + CRNode* m_pUList; // the head node + +private: + CRNode* m_pLast; // the last node + +private: + CRcvUList(const CRcvUList&); + CRcvUList& operator=(const CRcvUList&); +}; + +class CHash +{ +public: + CHash(); + ~CHash(); + +public: + /// Initialize the hash table. + /// @param [in] size hash table size + + void init(int size); + + /// Look for a UDT instance from the hash table. + /// @param [in] id socket ID + /// @return Pointer to a UDT instance, or NULL if not found. + + CUDT* lookup(int32_t id); + + /// Insert an entry to the hash table. + /// @param [in] id socket ID + /// @param [in] u pointer to the UDT instance + + void insert(int32_t id, CUDT* u); + + /// Remove an entry from the hash table. + /// @param [in] id socket ID + + void remove(int32_t id); + +private: + struct CBucket + { + int32_t m_iID; // Socket ID + CUDT* m_pUDT; // Socket instance + + CBucket* m_pNext; // next bucket + } * *m_pBucket; // list of buckets (the hash table) + + int m_iHashSize; // size of hash table + +private: + CHash(const CHash&); + CHash& operator=(const CHash&); +}; + +/// @brief A queue of sockets pending for connection. +/// It can be either a caller socket in a non-blocking mode +/// (the connection has to be handled in background), +/// or a socket in rendezvous connection mode. +class CRendezvousQueue +{ +public: + CRendezvousQueue(); + ~CRendezvousQueue(); + +public: + /// @brief Insert a new socket pending for connection (non-blocking caller or rendezvous). + /// @param id socket ID. + /// @param u pointer to a corresponding CUDT instance. + /// @param addr remote address to connect to. + /// @param ttl timepoint for connection attempt to expire. + void insert(const SRTSOCKET& id, CUDT* u, const sockaddr_any& addr, const srt::sync::steady_clock::time_point& ttl); + + /// @brief Remove a socket from the connection pending list. + /// @param id socket ID. + void remove(const SRTSOCKET& id); + + /// @brief Locate a socket in the connection pending queue. + /// @param addr source address of the packet received over UDP (peer address). + /// @param id socket ID. + /// @return a pointer to CUDT instance retrieved, or NULL if nothing was found. + CUDT* retrieve(const sockaddr_any& addr, SRTSOCKET& id) const; + + /// @brief Update status of connections in the pending queue. + /// Stop connecting if TTL expires. Resend handshake request every 250 ms if no response from the peer. + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param pktIn packet received from the UDP socket. + void updateConnStatus(EReadStatus rst, EConnectStatus cst, CUnit* unit); + +private: + struct LinkStatusInfo + { + CUDT* u; + SRTSOCKET id; + int errorcode; + sockaddr_any peeraddr; + int token; + + struct HasID + { + SRTSOCKET id; + HasID(SRTSOCKET p) + : id(p) + { + } + bool operator()(const LinkStatusInfo& i) { return i.id == id; } + }; + }; + + /// @brief Qualify pending connections: + /// - Sockets with expired TTL go to the 'to_remove' list and removed from the queue straight away. + /// - If HS request is to be resent (resend 250 ms if no response from the peer) go to the 'to_process' list. + /// + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param iDstSockID destination socket ID of the received packet. + /// @param[in,out] toRemove stores sockets with expired TTL. + /// @param[in,out] toProcess stores sockets which should repeat (resend) HS connection request. + bool qualifyToHandle(EReadStatus rst, + EConnectStatus cst, + int iDstSockID, + std::vector& toRemove, + std::vector& toProcess); + +private: + struct CRL + { + SRTSOCKET m_iID; // SRT socket ID (self) + CUDT* m_pUDT; // CUDT instance + sockaddr_any m_PeerAddr; // SRT sonnection peer address + sync::steady_clock::time_point m_tsTTL; // the time that this request expires + }; + std::list m_lRendezvousID; // The sockets currently in rendezvous mode + + mutable sync::Mutex m_RIDListLock; +}; + +class CSndQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CSndQueue(); + ~CSndQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the sending queue. + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t Timer + void init(CChannel* c, sync::CTimer* t); + + /// Send out a packet to a given address. The @a src parameter is + /// blindly passed by the caller down the call with intention to + /// be received eventually by CChannel::sendto, and used only if + /// appropriate conditions state so. + /// @param [in] addr destination address + /// @param [in,ref] packet packet to be sent out + /// @param [in] src The source IP address (details above) + /// @return Size of data sent out. + int sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& src); + + /// Get the IP TTL. + /// @param [in] ttl IP Time To Live. + /// @return TTL. + int getIpTTL() const; + + /// Get the IP Type of Service. + /// @return ToS. + int getIpToS() const; + +#ifdef SRT_ENABLE_BINDTODEVICE + bool getBind(char* dst, size_t len) const; +#endif + + int ioctlQuery(int type) const; + int sockoptQuery(int level, int type) const; + + void setClosing() { m_bClosing = true; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + +private: + CSndUList* m_pSndUList; // List of UDT instances for data sending + CChannel* m_pChannel; // The UDP channel for data sending + sync::CTimer* m_pTimer; // Timing facility + + sync::atomic m_bClosing; // closing the worker + +public: +#if defined(SRT_DEBUG_SNDQ_HIGHRATE) //>>debug high freq worker + sync::steady_clock::duration m_DbgPeriod; + mutable sync::steady_clock::time_point m_DbgTime; + struct + { + unsigned long lIteration; // + unsigned long lSleepTo; // SleepTo + unsigned long lNotReadyPop; // Continue + unsigned long lSendTo; + unsigned long lNotReadyTs; + unsigned long lCondWait; // block on m_WindowCond + } mutable m_WorkerStats; +#endif /* SRT_DEBUG_SNDQ_HIGHRATE */ + +private: + +#if ENABLE_LOGGING + static int m_counter; +#endif + + CSndQueue(const CSndQueue&); + CSndQueue& operator=(const CSndQueue&); +}; + +class CRcvQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CRcvQueue(); + ~CRcvQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the receiving queue. + /// @param [in] size queue size + /// @param [in] mss maximum packet size + /// @param [in] version IP version + /// @param [in] hsize hash table size + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t timer + void init(int size, size_t payload, int version, int hsize, CChannel* c, sync::CTimer* t); + + /// Read a packet for a specific UDT socket id. + /// @param [in] id Socket ID + /// @param [out] packet received packet + /// @return Data size of the packet + int recvfrom(int32_t id, CPacket& to_packet); + + void stopWorker(); + + void setClosing() { m_bClosing = true; } + + int getIPversion() { return m_iIPversion; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + // Subroutines of worker + EReadStatus worker_RetrieveUnit(int32_t& id, CUnit*& unit, sockaddr_any& sa); + EConnectStatus worker_ProcessConnectionRequest(CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_TryAsyncRend_OrStore(int32_t id, CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr_any& sa); + +private: + CUnitQueue* m_pUnitQueue; // The received packet queue + CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue + CHash* m_pHash; // Hash table for UDT socket looking up + CChannel* m_pChannel; // UDP channel for receiving packets + sync::CTimer* m_pTimer; // shared timer with the snd queue + + int m_iIPversion; // IP version + size_t m_szPayloadSize; // packet payload size + + sync::atomic m_bClosing; // closing the worker +#if ENABLE_LOGGING + static srt::sync::atomic m_counter; // A static counter to log RcvQueue worker thread number. +#endif + +private: + int setListener(CUDT* u); + void removeListener(const CUDT* u); + + void registerConnector(const SRTSOCKET& id, + CUDT* u, + const sockaddr_any& addr, + const sync::steady_clock::time_point& ttl); + void removeConnector(const SRTSOCKET& id); + + void setNewEntry(CUDT* u); + bool ifNewEntry(); + CUDT* getNewEntry(); + + void storePktClone(int32_t id, const CPacket& pkt); + +private: + sync::Mutex m_LSLock; + CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity + CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode + + std::vector m_vNewEntry; // newly added entries, to be inserted + sync::Mutex m_IDLock; + + std::map > m_mBuffer; // temporary buffer for rendezvous connection request + sync::Mutex m_BufferLock; + sync::Condition m_BufferCond; + +private: + CRcvQueue(const CRcvQueue&); + CRcvQueue& operator=(const CRcvQueue&); +}; + +struct CMultiplexer +{ + CSndQueue* m_pSndQueue; // The sending queue + CRcvQueue* m_pRcvQueue; // The receiving queue + CChannel* m_pChannel; // The UDP channel for sending and receiving + sync::CTimer* m_pTimer; // The timer + + int m_iPort; // The UDP port number of this multiplexer + int m_iIPversion; // Address family (AF_INET or AF_INET6) + int m_iRefCount; // number of UDT instances that are associated with this multiplexer + + CSrtMuxerConfig m_mcfg; + + int m_iID; // multiplexer ID + + // Constructor should reset all pointers to NULL + // to prevent dangling pointer when checking for memory alloc fails + CMultiplexer() + : m_pSndQueue(NULL) + , m_pRcvQueue(NULL) + , m_pChannel(NULL) + , m_pTimer(NULL) + { + } + + void destroy(); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/socketconfig.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/socketconfig.h new file mode 100644 index 000000000..403616edf --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/socketconfig.h @@ -0,0 +1,410 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_SOCKETCONFIG_H +#define INC_SRT_SOCKETCONFIG_H + +#include "platform_sys.h" +#ifdef SRT_ENABLE_BINDTODEVICE +#include +#endif +#include +#include "haicrypt.h" +#include "congctl.h" +#include "packet.h" +#include "handshake.h" +#include "logger_defs.h" +#include "packetfilter.h" + +// SRT Version constants +#define SRT_VERSION_UNK 0 +#define SRT_VERSION_MAJ1 0x010000 /* Version 1 major */ +#define SRT_VERSION_MAJ(v) (0xFF0000 & (v)) /* Major number ensuring backward compatibility */ +#define SRT_VERSION_MIN(v) (0x00FF00 & (v)) +#define SRT_VERSION_PCH(v) (0x0000FF & (v)) + +// NOTE: SRT_VERSION is primarily defined in the build file. +extern const int32_t SRT_DEF_VERSION; + +namespace srt +{ + +struct CSrtMuxerConfig +{ + static const int DEF_UDP_BUFFER_SIZE = 65536; + + int iIpTTL; + int iIpToS; + int iIpV6Only; // IPV6_V6ONLY option (-1 if not set) + bool bReuseAddr; // reuse an exiting port or not, for UDP multiplexer + +#ifdef SRT_ENABLE_BINDTODEVICE + std::string sBindToDevice; +#endif + int iUDPSndBufSize; // UDP sending buffer size + int iUDPRcvBufSize; // UDP receiving buffer size + + // NOTE: this operator is not reversable. The syntax must use: + // muxer_entry == socket_entry + bool isCompatWith(const CSrtMuxerConfig& other) const + { +#define CEQUAL(field) (field == other.field) + return CEQUAL(iIpTTL) + && CEQUAL(iIpToS) + && CEQUAL(bReuseAddr) +#ifdef SRT_ENABLE_BINDTODEVICE + && CEQUAL(sBindToDevice) +#endif + && CEQUAL(iUDPSndBufSize) + && CEQUAL(iUDPRcvBufSize) + && (other.iIpV6Only == -1 || CEQUAL(iIpV6Only)) + // NOTE: iIpV6Only is not regarded because + // this matches only in case of IPv6 with "any" address. + // And this aspect must be checked separately because here + // this procedure has no access to neither the address, + // nor the IP version (family). +#undef CEQUAL + && true; + } + + CSrtMuxerConfig() + : iIpTTL(-1) /* IPv4 TTL or IPv6 HOPs [1..255] (-1:undefined) */ + , iIpToS(-1) /* IPv4 Type of Service or IPv6 Traffic Class [0x00..0xff] (-1:undefined) */ + , iIpV6Only(-1) + , bReuseAddr(true) // This is default in SRT + , iUDPSndBufSize(DEF_UDP_BUFFER_SIZE) + , iUDPRcvBufSize(DEF_UDP_BUFFER_SIZE) + { + } +}; + +struct CSrtConfig; + +template +class StringStorage +{ + char stor[SIZE + 1]; + uint16_t len; + + // NOTE: default copying allowed. + +public: + StringStorage() + : len(0) + { + memset(stor, 0, sizeof stor); + } + + bool set(const char* s, size_t length) + { + if (length > SIZE) + return false; + + memcpy(stor, s, length); + stor[length] = 0; + len = (int) length; + return true; + } + + bool set(const std::string& s) + { + return set(s.c_str(), s.size()); + } + + size_t copy(char* s, size_t length) const + { + if (!s) + return 0; + + size_t copy_len = std::min((size_t)len, length); + memcpy(s, stor, copy_len); + return copy_len; + } + + std::string str() const + { + return len == 0 ? std::string() : std::string(stor); + } + + const char* c_str() const + { + return stor; + } + + size_t size() const { return size_t(len); } + bool empty() const { return len == 0; } +}; + +struct CSrtConfig: CSrtMuxerConfig +{ + typedef srt::sync::steady_clock::time_point time_point; + typedef srt::sync::steady_clock::duration duration; + + static const int + DEF_MSS = 1500, + DEF_FLIGHT_SIZE = 25600, + DEF_BUFFER_SIZE = 8192, //Rcv buffer MUST NOT be bigger than Flight Flag size + DEF_LINGER_S = 3*60, // 3 minutes + DEF_CONNTIMEO_S = 3; // 3 seconds + + enum + { + CIPHER_MODE_AUTO = 0, + CIPHER_MODE_AES_CTR = 1, + CIPHER_MODE_AES_GCM = 2 + }; + + static const int COMM_RESPONSE_TIMEOUT_MS = 5 * 1000; // 5 seconds + static const uint32_t COMM_DEF_MIN_STABILITY_TIMEOUT_MS = 60; // 60 ms + + // Mimimum recv flight flag size is 32 packets + static const int DEF_MIN_FLIGHT_PKT = 32; + static const size_t MAX_SID_LENGTH = 512; + static const size_t MAX_PFILTER_LENGTH = 64; + static const size_t MAX_CONG_LENGTH = 16; + + int iMSS; // Maximum Segment Size, in bytes + size_t zExpPayloadSize; // Expected average payload size (user option) + + // Options + bool bSynSending; // Sending synchronization mode + bool bSynRecving; // Receiving synchronization mode + int iFlightFlagSize; // Maximum number of packets in flight from the peer side + int iSndBufSize; // Maximum UDT sender buffer size + int iRcvBufSize; // Maximum UDT receiver buffer size + linger Linger; // Linger information on close + bool bRendezvous; // Rendezvous connection mode + + duration tdConnTimeOut; // connect timeout in milliseconds + bool bDriftTracer; + int iSndTimeOut; // sending timeout in milliseconds + int iRcvTimeOut; // receiving timeout in milliseconds + int64_t llMaxBW; // maximum data transfer rate (threshold) +#ifdef ENABLE_MAXREXMITBW + int64_t llMaxRexmitBW; // maximum bandwidth limit for retransmissions (Bytes/s). +#endif + + // These fields keep the options for encryption + // (SRTO_PASSPHRASE, SRTO_PBKEYLEN). Crypto object is + // created later and takes values from these. + HaiCrypt_Secret CryptoSecret; + int iSndCryptoKeyLen; + + // XXX Consider removing. The bDataSender stays here + // in order to maintain the HS side selection in HSv4. + bool bDataSender; + + bool bMessageAPI; + bool bTSBPD; // Whether AGENT will do TSBPD Rx (whether peer does, is not agent's problem) + int iRcvLatency; // Agent's Rx latency + int iPeerLatency; // Peer's Rx latency for the traffic made by Agent's Tx. + bool bTLPktDrop; // Whether Agent WILL DO TLPKTDROP on Rx. + int iSndDropDelay; // Extra delay when deciding to snd-drop for TLPKTDROP, -1 to off + bool bEnforcedEnc; // Off by default. When on, any connection other than nopw-nopw & pw1-pw1 is rejected. + int iGroupConnect; // 1 - allow group connections + int iPeerIdleTimeout_ms; // Timeout for hearing anything from the peer (ms). + uint32_t uMinStabilityTimeout_ms; + int iRetransmitAlgo; + int iCryptoMode; // SRTO_CRYPTOMODE + + int64_t llInputBW; // Input stream rate (bytes/sec). 0: use internally estimated input bandwidth + int64_t llMinInputBW; // Minimum input stream rate estimate (bytes/sec) + int iOverheadBW; // Percent above input stream rate (applies if llMaxBW == 0) + bool bRcvNakReport; // Enable Receiver Periodic NAK Reports + int iMaxReorderTolerance; //< Maximum allowed value for dynamic reorder tolerance + + // For the use of CCryptoControl + // HaiCrypt configuration + unsigned int uKmRefreshRatePkt; + unsigned int uKmPreAnnouncePkt; + + uint32_t uSrtVersion; + uint32_t uMinimumPeerSrtVersion; + + StringStorage sCongestion; + StringStorage sPacketFilterConfig; + StringStorage sStreamName; + + // Shortcuts and utilities + int32_t flightCapacity() + { + return std::min(iRcvBufSize, iFlightFlagSize); + } + + CSrtConfig() + : iMSS(DEF_MSS) + , zExpPayloadSize(SRT_LIVE_DEF_PLSIZE) + , bSynSending(true) + , bSynRecving(true) + , iFlightFlagSize(DEF_FLIGHT_SIZE) + , iSndBufSize(DEF_BUFFER_SIZE) + , iRcvBufSize(DEF_BUFFER_SIZE) + , bRendezvous(false) + , tdConnTimeOut(srt::sync::seconds_from(DEF_CONNTIMEO_S)) + , bDriftTracer(true) + , iSndTimeOut(-1) + , iRcvTimeOut(-1) + , llMaxBW(-1) +#ifdef ENABLE_MAXREXMITBW + , llMaxRexmitBW(-1) +#endif + , bDataSender(false) + , bMessageAPI(true) + , bTSBPD(true) + , iRcvLatency(SRT_LIVE_DEF_LATENCY_MS) + , iPeerLatency(0) + , bTLPktDrop(true) + , iSndDropDelay(0) + , bEnforcedEnc(true) + , iGroupConnect(0) + , iPeerIdleTimeout_ms(COMM_RESPONSE_TIMEOUT_MS) + , uMinStabilityTimeout_ms(COMM_DEF_MIN_STABILITY_TIMEOUT_MS) + , iRetransmitAlgo(1) + , iCryptoMode(CIPHER_MODE_AUTO) + , llInputBW(0) + , llMinInputBW(0) + , iOverheadBW(25) + , bRcvNakReport(true) + , iMaxReorderTolerance(0) // Sensible optimal value is 10, 0 preserves old behavior + , uKmRefreshRatePkt(0) + , uKmPreAnnouncePkt(0) + , uSrtVersion(SRT_DEF_VERSION) + , uMinimumPeerSrtVersion(SRT_VERSION_MAJ1) + + { + // Default UDT configurations + iUDPRcvBufSize = iRcvBufSize * iMSS; + + // Linger: LIVE mode defaults, please refer to `SRTO_TRANSTYPE` option + // for other modes. + Linger.l_onoff = 0; + Linger.l_linger = 0; + CryptoSecret.len = 0; + iSndCryptoKeyLen = 0; + + // Default congestion is "live". + // Available builtin congestions: "file". + // Others can be registerred. + sCongestion.set("live", 4); + } + + ~CSrtConfig() + { + // Wipeout critical data + memset(&CryptoSecret, 0, sizeof(CryptoSecret)); + } + + int set(SRT_SOCKOPT optName, const void* val, int size); +}; + +template +inline T cast_optval(const void* optval) +{ + return *reinterpret_cast(optval); +} + +template +inline T cast_optval(const void* optval, int optlen) +{ + if (optlen > 0 && optlen != sizeof(T)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + + return cast_optval(optval); +} + +// This function is to make it possible for both C and C++ +// API to accept both bool and int types for boolean options. +// (it's not that C couldn't use , it's that people +// often forget to use correct type). +template <> +inline bool cast_optval(const void* optval, int optlen) +{ + if (optlen == sizeof(bool)) + { + return *reinterpret_cast(optval); + } + + if (optlen == sizeof(int)) + { + // 0!= is a windows warning-killer int-to-bool conversion + return 0 != *reinterpret_cast(optval); + } + return false; +} + +} // namespace srt + +struct SRT_SocketOptionObject +{ + struct SingleOption + { + uint16_t option; + uint16_t length; + unsigned char storage[1]; // NOTE: Variable length object! + }; + + std::vector options; + + SRT_SocketOptionObject() {} + + ~SRT_SocketOptionObject() + { + for (size_t i = 0; i < options.size(); ++i) + { + // Convert back + unsigned char* mem = reinterpret_cast(options[i]); + delete[] mem; + } + } + + bool add(SRT_SOCKOPT optname, const void* optval, size_t optlen); +}; + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt.h index 0e566e859..53b6fd274 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt.h @@ -13,8 +13,8 @@ written by Haivision Systems Inc. *****************************************************************************/ -#ifndef INC__SRTC_H -#define INC__SRTC_H +#ifndef INC_SRTC_H +#define INC_SRTC_H #include "version.h" @@ -23,7 +23,6 @@ written by #include #include -#include "srt4udt.h" #include "logging_api.h" //////////////////////////////////////////////////////////////////////////////// @@ -36,7 +35,7 @@ written by #ifdef _WIN32 - #ifndef __MINGW__ + #ifndef __MINGW32__ // Explicitly define 32-bit and 64-bit numbers typedef __int32 int32_t; typedef __int64 int64_t; @@ -47,17 +46,14 @@ written by // VC 6.0 does not support unsigned __int64: may cause potential problems. typedef __int64 uint64_t; #endif - - #ifdef SRT_DYNAMIC - #ifdef SRT_EXPORTS - #define SRT_API __declspec(dllexport) - #else - #define SRT_API __declspec(dllimport) - #endif + #endif + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) #else - #define SRT_API + #define SRT_API __declspec(dllimport) #endif - #else // __MINGW__ + #else // !SRT_DYNAMIC #define SRT_API #endif #else @@ -69,48 +65,99 @@ written by // You can use these constants with SRTO_MINVERSION option. #define SRT_VERSION_FEAT_HSv5 0x010300 +#if defined(__cplusplus) && __cplusplus > 201406 +#define SRT_HAVE_CXX17 1 +#else +#define SRT_HAVE_CXX17 0 +#endif + + +// Standard attributes + // When compiling in C++17 mode, use the standard C++17 attributes // (out of these, only [[deprecated]] is supported in C++14, so // for all lesser standard use compiler-specific attributes). -#if defined(SRT_NO_DEPRECATED) - -#define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED -#define SRT_ATR_NODISCARD - -#elif defined(__cplusplus) && __cplusplus > 201406 +#if SRT_HAVE_CXX17 +// Unused: DO NOT issue a warning if this entity is unused. #define SRT_ATR_UNUSED [[maybe_unused]] -#define SRT_ATR_DEPRECATED [[deprecated]] + +// Nodiscard: issue a warning if the return value was discarded. #define SRT_ATR_NODISCARD [[nodiscard]] // GNUG is GNU C/C++; this syntax is also supported by Clang -#elif defined( __GNUC__) +#elif defined(__GNUC__) #define SRT_ATR_UNUSED __attribute__((unused)) -#define SRT_ATR_DEPRECATED __attribute__((deprecated)) #define SRT_ATR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define SRT_ATR_UNUSED __pragma(warning(suppress: 4100 4101)) +#define SRT_ATR_NODISCARD _Check_return_ #else #define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED #define SRT_ATR_NODISCARD #endif + +// DEPRECATED attributes + +// There's needed DEPRECATED and DEPRECATED_PX, as some compilers require them +// before the entity, others after the entity. +// The *_PX version is the prefix attribute, which applies only +// to functions (Microsoft compilers). + +// When deprecating a function, mark it: +// +// SRT_ATR_DEPRECATED_PX retval function(arguments) SRT_ATR_DEPRECATED; +// + +// When SRT_NO_DEPRECATED defined, do not issue any deprecation warnings. +// Regardless of the compiler type. +#if defined(SRT_NO_DEPRECATED) + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX + +#elif SRT_HAVE_CXX17 + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX [[deprecated]] + +// GNUG is GNU C/C++; this syntax is also supported by Clang +#elif defined(__GNUC__) +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SRT_ATR_DEPRECATED_PX __declspec(deprecated) +#define SRT_ATR_DEPRECATED // no postfix-type modifier +#else +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED +#endif + #ifdef __cplusplus extern "C" { #endif -typedef int SRTSOCKET; // SRTSOCKET is a typedef to int anyway, and it's not even in UDT namespace :) +typedef int32_t SRTSOCKET; + +// The most significant bit 31 (sign bit actually) is left unused, +// so that all people who check the value for < 0 instead of -1 +// still get what they want. The bit 30 is reserved for marking +// the "socket group". Most of the API functions should work +// transparently with the socket descriptor designating a single +// socket or a socket group. +static const int32_t SRTGROUP_MASK = (1 << 30); #ifdef _WIN32 - #ifndef __MINGW__ - typedef SOCKET SYSSOCKET; - #else - typedef int SYSSOCKET; - #endif + typedef SOCKET SYSSOCKET; #else typedef int SYSSOCKET; #endif +#ifndef ENABLE_BONDING +#define ENABLE_BONDING 0 +#endif + typedef SYSSOCKET UDPSOCKET; @@ -141,8 +188,7 @@ typedef enum SRT_SOCKOPT { SRTO_LINGER = 7, // waiting for unsent data when closing SRTO_UDP_SNDBUF = 8, // UDP sending buffer size SRTO_UDP_RCVBUF = 9, // UDP receiving buffer size - // XXX Free space for 2 options - // after deprecated ones are removed + // (some space left) SRTO_RENDEZVOUS = 12, // rendezvous connection mode SRTO_SNDTIMEO = 13, // send() timeout SRTO_RCVTIMEO = 14, // recv() timeout @@ -155,11 +201,10 @@ typedef enum SRT_SOCKOPT { SRTO_SENDER = 21, // Sender mode (independent of conn mode), for encryption, tsbpd handshake. SRTO_TSBPDMODE = 22, // Enable/Disable TsbPd. Enable -> Tx set origin timestamp, Rx deliver packet at origin time + delay SRTO_LATENCY = 23, // NOT RECOMMENDED. SET: to both SRTO_RCVLATENCY and SRTO_PEERLATENCY. GET: same as SRTO_RCVLATENCY. - SRTO_TSBPDDELAY = 23, // DEPRECATED. ALIAS: SRTO_LATENCY SRTO_INPUTBW = 24, // Estimated input stream rate. SRTO_OHEADBW, // MaxBW ceiling based on % over input stream rate. Applies when UDT_MAXBW=0 (auto). - SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto - SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (128-bit) + SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase (must be 10..79 characters, or empty to disable encryption) + SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (AES-128) SRTO_KMSTATE, // Key Material exchange status (UDT_SRTKmState) SRTO_IPTTL = 29, // IP Time To Live (passthru for system sockopt IPPROTO_IP/IP_TTL) SRTO_IPTOS, // IP Type of Service (passthru for system sockopt IPPROTO_IP/IP_TOS) @@ -168,10 +213,10 @@ typedef enum SRT_SOCKOPT { SRTO_NAKREPORT = 33, // Enable receiver to send periodic NAK reports SRTO_VERSION = 34, // Local SRT Version SRTO_PEERVERSION, // Peer SRT Version (from SRT Handshake) - SRTO_CONNTIMEO = 36, // Connect timeout in msec. Ccaller default: 3000, rendezvous (x 10) - // deprecated: SRTO_TWOWAYDATA, SRTO_SNDPBKEYLEN, SRTO_RCVPBKEYLEN (@c below) - _DEPRECATED_SRTO_SNDPBKEYLEN = 38, // (needed to use inside the code without generating -Wswitch) - // + SRTO_CONNTIMEO = 36, // Connect timeout in msec. Caller default: 3000, rendezvous (x 10) + SRTO_DRIFTTRACER = 37, // Enable or disable drift tracer + SRTO_MININPUTBW = 38, // Minimum estimate of input stream rate. + // (some space left) SRTO_SNDKMSTATE = 40, // (GET) the current state of the encryption at the peer side SRTO_RCVKMSTATE, // (GET) the current state of the encryption at the agent side SRTO_LOSSMAXTTL, // Maximum possible packet reorder tolerance (number of packets to receive after loss to send lossreport) @@ -188,15 +233,40 @@ typedef enum SRT_SOCKOPT { SRTO_ENFORCEDENCRYPTION, // Connection to be rejected or quickly broken when one side encryption set or bad password SRTO_IPV6ONLY, // IPV6_V6ONLY mode SRTO_PEERIDLETIMEO, // Peer-idle timeout (max time of silence heard from peer) in [ms] - // (some space left) - SRTO_PACKETFILTER = 60 // Add and configure a packet filter + SRTO_BINDTODEVICE, // Forward the SOL_SOCKET/SO_BINDTODEVICE option on socket (pass packets only from that device) + SRTO_GROUPCONNECT, // Set on a listener to allow group connection (ENABLE_BONDING) + SRTO_GROUPMINSTABLETIMEO, // Minimum Link Stability timeout (backup mode) in milliseconds (ENABLE_BONDING) + SRTO_GROUPTYPE, // Group type to which an accepted socket is about to be added, available in the handshake (ENABLE_BONDING) + SRTO_PACKETFILTER = 60, // Add and configure a packet filter + SRTO_RETRANSMITALGO = 61, // An option to select packet retransmission algorithm +#ifdef ENABLE_AEAD_API_PREVIEW + SRTO_CRYPTOMODE = 62, // Encryption cipher mode (AES-CTR, AES-GCM, ...). +#endif +#ifdef ENABLE_MAXREXMITBW + SRTO_MAXREXMITBW = 63, // Maximum bandwidth limit for retransmision (Bytes/s) +#endif + + SRTO_E_SIZE // Always last element, not a valid option. } SRT_SOCKOPT; #ifdef __cplusplus -typedef SRT_ATR_DEPRECATED SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED; + +#if __cplusplus > 199711L // C++11 + // Newer compilers report error when [[deprecated]] is applied to types, + // and C++11 and higher uses this. + // Note that this doesn't exactly use the 'deprecated' attribute, + // as it's introduced in C++14. What is actually used here is the + // fact that unknown attributes are ignored, but still warned about. + // This should only catch an eye - and that's what it does. +#define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT [[deprecated]])value) +#else + // Older (pre-C++11) compilers use gcc deprecated applied to a typedef + typedef SRT_ATR_DEPRECATED_PX SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED SRT_ATR_DEPRECATED; #define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT_DEPRECATED)value) +#endif + #else @@ -213,46 +283,9 @@ enum SRT_ATR_DEPRECATED SRT_SOCKOPT_DEPRECATED #define SRT_DEPRECATED_OPTION(value) ((enum SRT_SOCKOPT_DEPRECATED)value) #endif -// DEPRECATED OPTIONS: - -// SRTO_TWOWAYDATA: not to be used. SRT connection is always bidirectional if -// both clients support HSv5 - that is, since version 1.3.0. This flag was -// introducted around 1.2.0 version when full bidirectional support was added, -// but the bidirectional feature was decided no to be enabled due to huge -// differences between bidirectional support (especially concerning encryption) -// with HSv4 and HSv5 (that is, HSv4 was decided to remain unidirectional only, -// even though partial support is already provided in this version). - -#define SRTO_TWOWAYDATA SRT_DEPRECATED_OPTION(37) - -// This has been deprecated a long time ago, treat this as never implemented. -// The value is also already reused for another option. -#define SRTO_TSBPDMAXLAG SRT_DEPRECATED_OPTION(32) - -// This option is a derivative from UDT; the mechanism that uses it is now -// settable by SRTO_CONGESTION, or more generally by SRTO_TRANSTYPE. The freed -// number has been reused for a read-only option SRTO_ISN. This option should -// have never been used anywhere, just for safety this is temporarily declared -// as deprecated. -#define SRTO_CC SRT_DEPRECATED_OPTION(3) - -// These two flags were derived from UDT, but they were never used. -// Probably it didn't make sense anyway. The maximum size of the message -// in File/Message mode is defined by SRTO_SNDBUF, and the MSGTTL is -// a parameter used in `srt_sendmsg` and `srt_sendmsg2`. -#define SRTO_MAXMSG SRT_DEPRECATED_OPTION(10) -#define SRTO_MSGTTL SRT_DEPRECATED_OPTION(11) - -// These flags come from an older experimental implementation of bidirectional -// encryption support, which were used two different SEKs, KEKs and passphrases -// per direction. The current implementation uses just one in both directions, -// so SRTO_PBKEYLEN should be used for both cases. -#define SRTO_SNDPBKEYLEN SRT_DEPRECATED_OPTION(38) -#define SRTO_RCVPBKEYLEN SRT_DEPRECATED_OPTION(39) - -// Keeping old name for compatibility (deprecated) -#define SRTO_SMOOTHER SRT_DEPRECATED_OPTION(47) -#define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) +// Note that there are no deprecated options at the moment, but the mechanism +// stays so that it can be used in future. Example: +// #define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) typedef enum SRT_TRANSTYPE { @@ -295,9 +328,7 @@ struct CBytePerfMon int pktRcvUndecryptTotal; // number of undecrypted packets uint64_t byteSentTotal; // total number of sent data bytes, including retransmissions uint64_t byteRecvTotal; // total number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLossTotal; // total number of lost bytes -#endif uint64_t byteRetransTotal; // total number of retransmitted bytes uint64_t byteSndDropTotal; // number of too-late-to-send dropped bytes uint64_t byteRcvDropTotal; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -327,9 +358,7 @@ struct CBytePerfMon int pktRcvUndecrypt; // number of undecrypted packets uint64_t byteSent; // number of sent data bytes, including retransmissions uint64_t byteRecv; // number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLoss; // number of retransmitted bytes -#endif uint64_t byteRetrans; // number of retransmitted bytes uint64_t byteSndDrop; // number of too-late-to-send dropped bytes uint64_t byteRcvDrop; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -370,6 +399,20 @@ struct CBytePerfMon int pktRcvFilterLoss; // number of packet loss not coverable by filter int pktReorderTolerance; // packet reorder tolerance value //< + + // New stats in 1.5.0 + + // Total + int64_t pktSentUniqueTotal; // total number of data packets sent by the application + int64_t pktRecvUniqueTotal; // total number of packets to be received by the application + uint64_t byteSentUniqueTotal; // total number of data bytes, sent by the application + uint64_t byteRecvUniqueTotal; // total number of data bytes to be received by the application + + // Local + int64_t pktSentUnique; // number of data packets sent by the application + int64_t pktRecvUnique; // number of packets to be received by the application + uint64_t byteSentUnique; // number of data bytes, sent by the application + uint64_t byteRecvUnique; // number of data bytes to be received by the application }; //////////////////////////////////////////////////////////////////////////////// @@ -399,12 +442,14 @@ enum CodeMinor MN_REJECTED = 2, MN_NORES = 3, MN_SECURITY = 4, + MN_CLOSED = 5, // MJ_CONNECTION MN_CONNLOST = 1, MN_NOCONN = 2, // MJ_SYSTEMRES MN_THREAD = 1, MN_MEMORY = 2, + MN_OBJECT = 3, // MJ_FILESYSTEM MN_SEEKGFAIL = 1, MN_READFAIL = 2, @@ -424,6 +469,8 @@ enum CodeMinor MN_BUSY = 11, MN_XSIZE = 12, MN_EIDINVAL = 13, + MN_EEMPTY = 14, + MN_BUSYPORT = 15, // MJ_AGAIN MN_WRAVAIL = 1, MN_RDAVAIL = 2, @@ -431,12 +478,10 @@ enum CodeMinor MN_CONGESTION = 4 }; -static const enum CodeMinor MN_ISSTREAM SRT_ATR_DEPRECATED = (enum CodeMinor)(9); -static const enum CodeMinor MN_ISDGRAM SRT_ATR_DEPRECATED = (enum CodeMinor)(10); // Stupid, but effective. This will be #undefined, so don't worry. -#define MJ(major) (1000 * MJ_##major) -#define MN(major, minor) (1000 * MJ_##major + MN_##minor) +#define SRT_EMJ(major) (1000 * MJ_##major) +#define SRT_EMN(major, minor) (1000 * MJ_##major + MN_##minor) // Some better way to define it, and better for C language. typedef enum SRT_ERRNO @@ -444,55 +489,56 @@ typedef enum SRT_ERRNO SRT_EUNKNOWN = -1, SRT_SUCCESS = MJ_SUCCESS, - SRT_ECONNSETUP = MJ(SETUP), - SRT_ENOSERVER = MN(SETUP, TIMEOUT), - SRT_ECONNREJ = MN(SETUP, REJECTED), - SRT_ESOCKFAIL = MN(SETUP, NORES), - SRT_ESECFAIL = MN(SETUP, SECURITY), - - SRT_ECONNFAIL = MJ(CONNECTION), - SRT_ECONNLOST = MN(CONNECTION, CONNLOST), - SRT_ENOCONN = MN(CONNECTION, NOCONN), - - SRT_ERESOURCE = MJ(SYSTEMRES), - SRT_ETHREAD = MN(SYSTEMRES, THREAD), - SRT_ENOBUF = MN(SYSTEMRES, MEMORY), - - SRT_EFILE = MJ(FILESYSTEM), - SRT_EINVRDOFF = MN(FILESYSTEM, SEEKGFAIL), - SRT_ERDPERM = MN(FILESYSTEM, READFAIL), - SRT_EINVWROFF = MN(FILESYSTEM, SEEKPFAIL), - SRT_EWRPERM = MN(FILESYSTEM, WRITEFAIL), - - SRT_EINVOP = MJ(NOTSUP), - SRT_EBOUNDSOCK = MN(NOTSUP, ISBOUND), - SRT_ECONNSOCK = MN(NOTSUP, ISCONNECTED), - SRT_EINVPARAM = MN(NOTSUP, INVAL), - SRT_EINVSOCK = MN(NOTSUP, SIDINVAL), - SRT_EUNBOUNDSOCK = MN(NOTSUP, ISUNBOUND), - SRT_ENOLISTEN = MN(NOTSUP, NOLISTEN), - SRT_ERDVNOSERV = MN(NOTSUP, ISRENDEZVOUS), - SRT_ERDVUNBOUND = MN(NOTSUP, ISRENDUNBOUND), - SRT_EINVALMSGAPI = MN(NOTSUP, INVALMSGAPI), - SRT_EINVALBUFFERAPI = MN(NOTSUP, INVALBUFFERAPI), - SRT_EDUPLISTEN = MN(NOTSUP, BUSY), - SRT_ELARGEMSG = MN(NOTSUP, XSIZE), - SRT_EINVPOLLID = MN(NOTSUP, EIDINVAL), - - SRT_EASYNCFAIL = MJ(AGAIN), - SRT_EASYNCSND = MN(AGAIN, WRAVAIL), - SRT_EASYNCRCV = MN(AGAIN, RDAVAIL), - SRT_ETIMEOUT = MN(AGAIN, XMTIMEOUT), - SRT_ECONGEST = MN(AGAIN, CONGESTION), - - SRT_EPEERERR = MJ(PEERERROR) + SRT_ECONNSETUP = SRT_EMJ(SETUP), + SRT_ENOSERVER = SRT_EMN(SETUP, TIMEOUT), + SRT_ECONNREJ = SRT_EMN(SETUP, REJECTED), + SRT_ESOCKFAIL = SRT_EMN(SETUP, NORES), + SRT_ESECFAIL = SRT_EMN(SETUP, SECURITY), + SRT_ESCLOSED = SRT_EMN(SETUP, CLOSED), + + SRT_ECONNFAIL = SRT_EMJ(CONNECTION), + SRT_ECONNLOST = SRT_EMN(CONNECTION, CONNLOST), + SRT_ENOCONN = SRT_EMN(CONNECTION, NOCONN), + + SRT_ERESOURCE = SRT_EMJ(SYSTEMRES), + SRT_ETHREAD = SRT_EMN(SYSTEMRES, THREAD), + SRT_ENOBUF = SRT_EMN(SYSTEMRES, MEMORY), + SRT_ESYSOBJ = SRT_EMN(SYSTEMRES, OBJECT), + + SRT_EFILE = SRT_EMJ(FILESYSTEM), + SRT_EINVRDOFF = SRT_EMN(FILESYSTEM, SEEKGFAIL), + SRT_ERDPERM = SRT_EMN(FILESYSTEM, READFAIL), + SRT_EINVWROFF = SRT_EMN(FILESYSTEM, SEEKPFAIL), + SRT_EWRPERM = SRT_EMN(FILESYSTEM, WRITEFAIL), + + SRT_EINVOP = SRT_EMJ(NOTSUP), + SRT_EBOUNDSOCK = SRT_EMN(NOTSUP, ISBOUND), + SRT_ECONNSOCK = SRT_EMN(NOTSUP, ISCONNECTED), + SRT_EINVPARAM = SRT_EMN(NOTSUP, INVAL), + SRT_EINVSOCK = SRT_EMN(NOTSUP, SIDINVAL), + SRT_EUNBOUNDSOCK = SRT_EMN(NOTSUP, ISUNBOUND), + SRT_ENOLISTEN = SRT_EMN(NOTSUP, NOLISTEN), + SRT_ERDVNOSERV = SRT_EMN(NOTSUP, ISRENDEZVOUS), + SRT_ERDVUNBOUND = SRT_EMN(NOTSUP, ISRENDUNBOUND), + SRT_EINVALMSGAPI = SRT_EMN(NOTSUP, INVALMSGAPI), + SRT_EINVALBUFFERAPI = SRT_EMN(NOTSUP, INVALBUFFERAPI), + SRT_EDUPLISTEN = SRT_EMN(NOTSUP, BUSY), + SRT_ELARGEMSG = SRT_EMN(NOTSUP, XSIZE), + SRT_EINVPOLLID = SRT_EMN(NOTSUP, EIDINVAL), + SRT_EPOLLEMPTY = SRT_EMN(NOTSUP, EEMPTY), + SRT_EBINDCONFLICT = SRT_EMN(NOTSUP, BUSYPORT), + + SRT_EASYNCFAIL = SRT_EMJ(AGAIN), + SRT_EASYNCSND = SRT_EMN(AGAIN, WRAVAIL), + SRT_EASYNCRCV = SRT_EMN(AGAIN, RDAVAIL), + SRT_ETIMEOUT = SRT_EMN(AGAIN, XMTIMEOUT), + SRT_ECONGEST = SRT_EMN(AGAIN, CONGESTION), + + SRT_EPEERERR = SRT_EMJ(PEERERROR) } SRT_ERRNO; -static const SRT_ERRNO SRT_EISSTREAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALMSGAPI); -static const SRT_ERRNO SRT_EISDGRAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALBUFFERAPI); - -#undef MJ -#undef MN +#undef SRT_EMJ +#undef SRT_EMN enum SRT_REJECT_REASON { @@ -510,56 +556,173 @@ enum SRT_REJECT_REASON SRT_REJ_UNSECURE, // password required or unexpected SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision SRT_REJ_CONGESTION, // incompatible congestion-controller type - SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_GROUP, // incompatible group + SRT_REJ_TIMEOUT, // connection timeout +#ifdef ENABLE_AEAD_API_PREVIEW + SRT_REJ_CRYPTO, // conflicting cryptographic configurations +#endif - SRT_REJ__SIZE, + SRT_REJ_E_SIZE, }; +// XXX This value remains for some time, but it's deprecated +// Planned deprecation removal: rel1.6.0. +#define SRT_REJ__SIZE SRT_REJ_E_SIZE + +// Reject category codes: + +#define SRT_REJC_VALUE(code) (1000 * (code/1000)) +#define SRT_REJC_INTERNAL 0 // Codes from above SRT_REJECT_REASON enum +#define SRT_REJC_PREDEFINED 1000 // Standard server error codes +#define SRT_REJC_USERDEFINED 2000 // User defined error codes + + // Logging API - specialization for SRT. -// Define logging functional areas for log selection. -// Use values greater than 0. Value 0 is reserved for LOGFA_GENERAL, -// which is considered always enabled. +// WARNING: This part is generated. // Logger Functional Areas // Note that 0 is "general". +// Values 0* - general, unqualified +// Values 1* - control +// Values 2* - receiving +// Values 3* - sending +// Values 4* - management + // Made by #define so that it's available also for C API. -#define SRT_LOGFA_GENERAL 0 -#define SRT_LOGFA_BSTATS 1 -#define SRT_LOGFA_CONTROL 2 -#define SRT_LOGFA_DATA 3 -#define SRT_LOGFA_TSBPD 4 -#define SRT_LOGFA_REXMIT 5 -#define SRT_LOGFA_HAICRYPT 6 -#define SRT_LOGFA_CONGEST 7 - -// To make a typical int32_t size, although still use std::bitset. + +// Use ../scripts/generate-logging-defs.tcl to regenerate. + +// SRT_LOGFA BEGIN GENERATED SECTION { + +#define SRT_LOGFA_GENERAL 0 // gglog: General uncategorized log, for serious issues only +#define SRT_LOGFA_SOCKMGMT 1 // smlog: Socket create/open/close/configure activities +#define SRT_LOGFA_CONN 2 // cnlog: Connection establishment and handshake +#define SRT_LOGFA_XTIMER 3 // xtlog: The checkTimer and around activities +#define SRT_LOGFA_TSBPD 4 // tslog: The TsBPD thread +#define SRT_LOGFA_RSRC 5 // rslog: System resource allocation and management + +#define SRT_LOGFA_CONGEST 7 // cclog: Congestion control module +#define SRT_LOGFA_PFILTER 8 // pflog: Packet filter module + +#define SRT_LOGFA_API_CTRL 11 // aclog: API part for socket and library managmenet + +#define SRT_LOGFA_QUE_CTRL 13 // qclog: Queue control activities + +#define SRT_LOGFA_EPOLL_UPD 16 // eilog: EPoll, internal update activities + +#define SRT_LOGFA_API_RECV 21 // arlog: API part for receiving +#define SRT_LOGFA_BUF_RECV 22 // brlog: Buffer, receiving side +#define SRT_LOGFA_QUE_RECV 23 // qrlog: Queue, receiving side +#define SRT_LOGFA_CHN_RECV 24 // krlog: CChannel, receiving side +#define SRT_LOGFA_GRP_RECV 25 // grlog: Group, receiving side + +#define SRT_LOGFA_API_SEND 31 // aslog: API part for sending +#define SRT_LOGFA_BUF_SEND 32 // bslog: Buffer, sending side +#define SRT_LOGFA_QUE_SEND 33 // qslog: Queue, sending side +#define SRT_LOGFA_CHN_SEND 34 // kslog: CChannel, sending side +#define SRT_LOGFA_GRP_SEND 35 // gslog: Group, sending side + +#define SRT_LOGFA_INTERNAL 41 // inlog: Internal activities not connected directly to a socket + +#define SRT_LOGFA_QUE_MGMT 43 // qmlog: Queue, management part +#define SRT_LOGFA_CHN_MGMT 44 // kmlog: CChannel, management part +#define SRT_LOGFA_GRP_MGMT 45 // gmlog: Group, management part +#define SRT_LOGFA_EPOLL_API 46 // ealog: EPoll, API part + +#define SRT_LOGFA_HAICRYPT 6 // hclog: Haicrypt module area +#define SRT_LOGFA_APPLOG 10 // aplog: Applications + +// } SRT_LOGFA END GENERATED SECTION + +// To make a typical int64_t size, although still use std::bitset. // C API will carry it over. -#define SRT_LOGFA_LASTNONE 31 +#define SRT_LOGFA_LASTNONE 63 enum SRT_KM_STATE { - SRT_KM_S_UNSECURED = 0, //No encryption - SRT_KM_S_SECURING = 1, //Stream encrypted, exchanging Keying Material - SRT_KM_S_SECURED = 2, //Stream encrypted, keying Material exchanged, decrypting ok. - SRT_KM_S_NOSECRET = 3, //Stream encrypted and no secret to decrypt Keying Material - SRT_KM_S_BADSECRET = 4 //Stream encrypted and wrong secret, cannot decrypt Keying Material + SRT_KM_S_UNSECURED = 0, // No encryption + SRT_KM_S_SECURING = 1, // Stream encrypted, exchanging Keying Material + SRT_KM_S_SECURED = 2, // Stream encrypted, keying Material exchanged, decrypting ok. + SRT_KM_S_NOSECRET = 3, // Stream encrypted and no secret to decrypt Keying Material + SRT_KM_S_BADSECRET = 4 // Stream encrypted and wrong secret is used, cannot decrypt Keying Material +#ifdef ENABLE_AEAD_API_PREVIEW + ,SRT_KM_S_BADCRYPTOMODE = 5 // Stream encrypted but wrong cryptographic mode is used, cannot decrypt. Since v1.5.2. +#endif }; enum SRT_EPOLL_OPT { SRT_EPOLL_OPT_NONE = 0x0, // fallback - // this values are defined same as linux epoll.h + + // Values intended to be the same as in ``. // so that if system values are used by mistake, they should have the same effect + // This applies to: IN, OUT, ERR and ET. + + /// Ready for 'recv' operation: + /// + /// - For stream mode it means that at least 1 byte is available. + /// In this mode the buffer may extract only a part of the packet, + /// leaving next data possible for extraction later. + /// + /// - For message mode it means that there is at least one packet + /// available (this may change in future, as it is desired that + /// one full message should only wake up, not single packet of a + /// not yet extractable message). + /// + /// - For live mode it means that there's at least one packet + /// ready to play. + /// + /// - For listener sockets, this means that there is a new connection + /// waiting for pickup through the `srt_accept()` call, that is, + /// the next call to `srt_accept()` will succeed without blocking + /// (see an alias SRT_EPOLL_ACCEPT below). SRT_EPOLL_IN = 0x1, + + /// Ready for 'send' operation. + /// + /// - For stream mode it means that there's a free space in the + /// sender buffer for at least 1 byte of data. The next send + /// operation will only allow to send as much data as it is free + /// space in the buffer. + /// + /// - For message mode it means that there's a free space for at + /// least one UDP packet. The edge-triggered mode can be used to + /// pick up updates as the free space in the sender buffer grows. + /// + /// - For live mode it means that there's a free space for at least + /// one UDP packet. On the other hand, no readiness for OUT usually + /// means an extraordinary congestion on the link, meaning also that + /// you should immediately slow down the sending rate or you may get + /// a connection break soon. + /// + /// - For non-blocking sockets used with `srt_connect*` operation, + /// this flag simply means that the connection was established. SRT_EPOLL_OUT = 0x4, + + /// The socket has encountered an error in the last operation + /// and the next operation on that socket will end up with error. + /// You can retry the operation, but getting the error from it + /// is certain, so you may as well close the socket. SRT_EPOLL_ERR = 0x8, + + // To avoid confusion in the internal code, the following + // duplicates are introduced to improve clarity. + SRT_EPOLL_CONNECT = SRT_EPOLL_OUT, + SRT_EPOLL_ACCEPT = SRT_EPOLL_IN, + + SRT_EPOLL_UPDATE = 0x10, SRT_EPOLL_ET = 1u << 31 }; // These are actually flags - use a bit container: typedef int32_t SRT_EPOLL_T; +// Define which epoll flags determine events. All others are special flags. +#define SRT_EPOLL_EVENTTYPES (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_UPDATE | SRT_EPOLL_ERR) +#define SRT_EPOLL_ETONLY (SRT_EPOLL_UPDATE) + enum SRT_EPOLL_FLAGS { /// This allows the EID container to be empty when calling the waiting @@ -582,17 +745,8 @@ inline SRT_EPOLL_OPT operator|(SRT_EPOLL_OPT a1, SRT_EPOLL_OPT a2) return SRT_EPOLL_OPT( (int)a1 | (int)a2 ); } -inline bool operator&(int flags, SRT_EPOLL_OPT eflg) -{ - // Using an enum prevents treating int automatically as enum, - // requires explicit enum to be passed here, and minimizes the - // risk that the right side value will contain multiple flags. - return (flags & int(eflg)) != 0; -} #endif - - typedef struct CBytePerfMon SRT_TRACEBSTATS; static const SRTSOCKET SRT_INVALID_SOCK = -1; @@ -605,18 +759,32 @@ SRT_API int srt_cleanup(void); // // Socket operations // -SRT_API SRTSOCKET srt_socket (int af, int type, int protocol); -SRT_API SRTSOCKET srt_create_socket(); +// DEPRECATED: srt_socket with 3 arguments. All these arguments are ignored +// and socket creation doesn't need any arguments. Use srt_create_socket(). +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX SRT_API SRTSOCKET srt_socket(int, int, int) SRT_ATR_DEPRECATED; +SRT_API SRTSOCKET srt_create_socket(void); + SRT_API int srt_bind (SRTSOCKET u, const struct sockaddr* name, int namelen); -SRT_API int srt_bind_peerof (SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int srt_bind_acquire (SRTSOCKET u, UDPSOCKET sys_udp_sock); +// Old name of srt_bind_acquire(), please don't use +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX static inline int srt_bind_peerof(SRTSOCKET u, UDPSOCKET sys_udp_sock) SRT_ATR_DEPRECATED; +static inline int srt_bind_peerof (SRTSOCKET u, UDPSOCKET sys_udp_sock) { return srt_bind_acquire(u, sys_udp_sock); } SRT_API int srt_listen (SRTSOCKET u, int backlog); SRT_API SRTSOCKET srt_accept (SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API SRTSOCKET srt_accept_bond (const SRTSOCKET listeners[], int lsize, int64_t msTimeOut); typedef int srt_listen_callback_fn (void* opaq, SRTSOCKET ns, int hsversion, const struct sockaddr* peeraddr, const char* streamid); SRT_API int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); +typedef void srt_connect_callback_fn (void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); +SRT_API int srt_connect_callback(SRTSOCKET clr, srt_connect_callback_fn* hook_fn, void* hook_opaque); SRT_API int srt_connect (SRTSOCKET u, const struct sockaddr* name, int namelen); SRT_API int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +SRT_API int srt_connect_bind (SRTSOCKET u, const struct sockaddr* source, + const struct sockaddr* target, int len); SRT_API int srt_rendezvous (SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, const struct sockaddr* remote_name, int remote_namelen); + SRT_API int srt_close (SRTSOCKET u); SRT_API int srt_getpeername (SRTSOCKET u, struct sockaddr* name, int* namelen); SRT_API int srt_getsockname (SRTSOCKET u, struct sockaddr* name, int* namelen); @@ -625,19 +793,34 @@ SRT_API int srt_setsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCK SRT_API int srt_getsockflag (SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); SRT_API int srt_setsockflag (SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); +typedef struct SRT_SocketGroupData_ SRT_SOCKGROUPDATA; -// XXX Note that the srctime functionality doesn't work yet and needs fixing. typedef struct SRT_MsgCtrl_ { int flags; // Left for future - int msgttl; // TTL for a message, default -1 (no TTL limitation) + int msgttl; // TTL for a message (millisec), default -1 (no TTL limitation) int inorder; // Whether a message is allowed to supersede partially lost one. Unused in stream and live mode. int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame - uint64_t srctime; // source timestamp (usec), 0: use internal time + int64_t srctime; // source time since epoch (usec), 0: use internal time (sender) int32_t pktseq; // sequence number of the first packet in received message (unused for sending) int32_t msgno; // message number (output value for both sending and receiving) + SRT_SOCKGROUPDATA* grpdata; + size_t grpdata_size; } SRT_MSGCTRL; +// Trap representation for sequence and message numbers +// This value means that this is "unset", and it's never +// a result of an operation made on this number. +static const int32_t SRT_SEQNO_NONE = -1; // -1: no seq (0 is a valid seqno!) +static const int32_t SRT_MSGNO_NONE = -1; // -1: unset +static const int32_t SRT_MSGNO_CONTROL = 0; // 0: control (used by packet filter) + +static const int SRT_MSGTTL_INF = -1; // unlimited TTL specification for message TTL + +// XXX Might be useful also other special uses of -1: +// - -1 as infinity for srt_epoll_wait +// - -1 as a trap index value used in list.cpp + // You are free to use either of these two methods to set SRT_MSGCTRL object // to default values: either call srt_msgctrl_init(&obj) or obj = srt_msgctrl_default. SRT_API void srt_msgctrl_init(SRT_MSGCTRL* mctrl); @@ -657,11 +840,6 @@ SRT_API extern const SRT_MSGCTRL srt_msgctrl_default; // parameters will be filled, as needed. NULL is acceptable, in which case // the defaults are used. -// NOTE: srt_send and srt_recv have the last "..." left to allow ignore a -// deprecated and unused "flags" parameter. After confirming that all -// compat applications that pass useless 0 there are fixed, this will be -// removed. - // // Sending functions // @@ -692,16 +870,17 @@ SRT_API int srt_getlasterror(int* errno_loc); SRT_API const char* srt_strerror(int code, int errnoval); SRT_API void srt_clearlasterror(void); -// performance track -// perfmon with Byte counters for better bitrate estimation. +// Performance tracking +// Performance monitor with Byte counters for better bitrate estimation. SRT_API int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); -// permon with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. +// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. SRT_API int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); // Socket Status (for problem tracking) SRT_API SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); SRT_API int srt_epoll_create(void); +SRT_API int srt_epoll_clear_usocks(int eid); SRT_API int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); SRT_API int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_remove_usock(int eid, SRTSOCKET u); @@ -711,10 +890,14 @@ SRT_API int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); -typedef struct SRT_EPOLL_EVENT_ +typedef struct SRT_EPOLL_EVENT_STR { SRTSOCKET fd; int events; // SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR +#ifdef __cplusplus + SRT_EPOLL_EVENT_STR(SRTSOCKET s, int ev): fd(s), events(ev) {} + SRT_EPOLL_EVENT_STR(): fd(-1), events(0) {} // NOTE: allows singular values, no init. +#endif } SRT_EPOLL_EVENT; SRT_API int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); @@ -736,9 +919,88 @@ SRT_API void srt_setlogflags(int flags); SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); -SRT_API enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); -SRT_API extern const char* const srt_rejectreason_msg []; -const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); +SRT_API int srt_getrejectreason(SRTSOCKET sock); +SRT_API int srt_setrejectreason(SRTSOCKET sock, int value); +// The srt_rejectreason_msg[] array is deprecated (as unsafe). +// Planned removal: v1.6.0. +SRT_API SRT_ATR_DEPRECATED extern const char* const srt_rejectreason_msg []; +SRT_API const char* srt_rejectreason_str(int id); + +SRT_API uint32_t srt_getversion(void); + +SRT_API int64_t srt_time_now(void); + +SRT_API int64_t srt_connection_time(SRTSOCKET sock); + +// Possible internal clock types +#define SRT_SYNC_CLOCK_STDCXX_STEADY 0 // C++11 std::chrono::steady_clock +#define SRT_SYNC_CLOCK_GETTIME_MONOTONIC 1 // clock_gettime with CLOCK_MONOTONIC +#define SRT_SYNC_CLOCK_WINQPC 2 +#define SRT_SYNC_CLOCK_MACH_ABSTIME 3 +#define SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY 4 +#define SRT_SYNC_CLOCK_AMD64_RDTSC 5 +#define SRT_SYNC_CLOCK_IA32_RDTSC 6 +#define SRT_SYNC_CLOCK_IA64_ITC 7 + +SRT_API int srt_clock_type(void); + +// SRT Socket Groups API (ENABLE_BONDING) + +typedef enum SRT_GROUP_TYPE +{ + SRT_GTYPE_UNDEFINED, + SRT_GTYPE_BROADCAST, + SRT_GTYPE_BACKUP, + // ... + SRT_GTYPE_E_END +} SRT_GROUP_TYPE; + +// Free-form flags for groups +// Flags may be type-specific! +static const uint32_t SRT_GFLAG_SYNCONMSG = 1; + +typedef enum SRT_MemberStatus +{ + SRT_GST_PENDING, // The socket is created correctly, but not yet ready for getting data. + SRT_GST_IDLE, // The socket is ready to be activated + SRT_GST_RUNNING, // The socket was already activated and is in use + SRT_GST_BROKEN // The last operation broke the socket, it should be closed. +} SRT_MEMBERSTATUS; + +struct SRT_SocketGroupData_ +{ + SRTSOCKET id; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + SRT_SOCKSTATUS sockstate; + uint16_t weight; + SRT_MEMBERSTATUS memberstate; + int result; + int token; +}; + +typedef struct SRT_SocketOptionObject SRT_SOCKOPT_CONFIG; + +typedef struct SRT_GroupMemberConfig_ +{ + SRTSOCKET id; + struct sockaddr_storage srcaddr; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + uint16_t weight; + SRT_SOCKOPT_CONFIG* config; + int errorcode; + int token; +} SRT_SOCKGROUPCONFIG; + +SRT_API SRTSOCKET srt_create_group(SRT_GROUP_TYPE); +SRT_API SRTSOCKET srt_groupof(SRTSOCKET socket); +SRT_API int srt_group_data(SRTSOCKET socketgroup, SRT_SOCKGROUPDATA* output, size_t* inoutlen); + +SRT_API SRT_SOCKOPT_CONFIG* srt_create_config(void); +SRT_API void srt_delete_config(SRT_SOCKOPT_CONFIG* config /*nullable*/); +SRT_API int srt_config_add(SRT_SOCKOPT_CONFIG* config, SRT_SOCKOPT option, const void* contents, int len); + +SRT_API SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, const struct sockaddr* adr, int namelen); +SRT_API int srt_connect_group(SRTSOCKET group, SRT_SOCKGROUPCONFIG name[], int arraysize); #ifdef __cplusplus } diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt4udt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt4udt.h deleted file mode 100644 index 49f6d9f7a..000000000 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt4udt.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -written by - Haivision Systems Inc. - *****************************************************************************/ - -#ifndef SRT4UDT_H -#define SRT4UDT_H - -#ifndef INC__SRTC_H -#error "This is protected header, used by udt.h. This shouldn't be included directly" -#endif - -//undef SRT_ENABLE_ECN 1 /* Early Congestion Notification (for source bitrate control) */ - -//undef SRT_DEBUG_TSBPD_OUTJITTER 1 /* Packet Delivery histogram */ -//undef SRT_DEBUG_TSBPD_DRIFT 1 /* Debug Encoder-Decoder Drift) */ -//undef SRT_DEBUG_TSBPD_WRAP 1 /* Debug packet timestamp wraparound */ -//undef SRT_DEBUG_TLPKTDROP_DROPSEQ 1 -//undef SRT_DEBUG_SNDQ_HIGHRATE 1 - - -/* -* SRT_ENABLE_CONNTIMEO -* Option UDT_CONNTIMEO added to the API to set/get the connection timeout. -* The UDT hard coded default of 3000 msec is too small for some large RTT (satellite) use cases. -* The SRT handshake (2 exchanges) needs 2 times the RTT to complete with no packet loss. -*/ -#define SRT_ENABLE_CONNTIMEO 1 - -/* -* SRT_ENABLE_NOCWND -* Set the congestion window at its max (then disabling it) to prevent stopping transmission -* when too many packets are not acknowledged. -* The congestion windows is the maximum distance in pkts since the last acknowledged packets. -*/ -#define SRT_ENABLE_NOCWND 1 - -/* -* SRT_ENABLE_NAKREPORT -* Send periodic NAK report for more efficient retransmission instead of relying on ACK timeout -* to retransmit all non-ACKed packets, very inefficient with real-time and no congestion window. -*/ -#define SRT_ENABLE_NAKREPORT 1 - -#define SRT_ENABLE_RCVBUFSZ_MAVG 1 /* Recv buffer size moving average */ -#define SRT_ENABLE_SNDBUFSZ_MAVG 1 /* Send buffer size moving average */ -#define SRT_MAVG_SAMPLING_RATE 40 /* Max sampling rate */ - -#define SRT_ENABLE_LOSTBYTESCOUNT 1 - - -/* -* SRT_ENABLE_IPOPTS -* Enable IP TTL and ToS setting -*/ -#define SRT_ENABLE_IPOPTS 1 - - -#define SRT_ENABLE_CLOSE_SYNCH 1 - -#endif /* SRT4UDT_H */ diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_attr_defs.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_attr_defs.h new file mode 100644 index 000000000..84daabeb1 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_attr_defs.h @@ -0,0 +1,191 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v.2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +/***************************************************************************** +The file contains various planform and compiler dependent attribute definitions +used by SRT library internally. + *****************************************************************************/ + +#ifndef INC_SRT_ATTR_DEFS_H +#define INC_SRT_ATTR_DEFS_H + +// ATTRIBUTES: +// +// SRT_ATR_UNUSED: declare an entity ALLOWED to be unused (prevents warnings) +// ATR_DEPRECATED: declare an entity deprecated (compiler should warn when used) +// ATR_NOEXCEPT: The true `noexcept` from C++11, or nothing if compiling in pre-C++11 mode +// ATR_NOTHROW: In C++11: `noexcept`. In pre-C++11: `throw()`. Required for GNU libstdc++. +// ATR_CONSTEXPR: In C++11: `constexpr`. Otherwise empty. +// ATR_OVERRIDE: In C++11: `override`. Otherwise empty. +// ATR_FINAL: In C++11: `final`. Otherwise empty. + +#ifdef __GNUG__ +#define ATR_DEPRECATED __attribute__((deprecated)) +#else +#define ATR_DEPRECATED +#endif + +#if defined(__cplusplus) && __cplusplus > 199711L +#define HAVE_CXX11 1 +// For gcc 4.7, claim C++11 is supported, as long as experimental C++0x is on, +// however it's only the "most required C++11 support". +#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 // 4.7 only! +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#else +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1800 +// Microsoft Visual Studio supports C++11, but not fully, +// and still did not change the value of __cplusplus. Treat +// this special way. +// _MSC_VER == 1800 means Microsoft Visual Studio 2013. +#define HAVE_CXX11 1 +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#else +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif +#else +#define HAVE_CXX11 0 +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif // __cplusplus + +#if !HAVE_CXX11 && defined(REQUIRE_CXX11) && REQUIRE_CXX11 == 1 +#error "The currently compiled application required C++11, but your compiler doesn't support it." +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Attributes for thread safety analysis +// - Clang TSA (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutexheader). +// - MSVC SAL (partially). +// - Other compilers: none. +/////////////////////////////////////////////////////////////////////////////// +#if _MSC_VER >= 1920 +// In case of MSVC these attributes have to precede the attributed objects (variable, function). +// E.g. SRT_ATTR_GUARDED_BY(mtx) int object; +// It is tricky to annotate e.g. the following function, as clang complaints it does not know 'm'. +// SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) +// inline void enterCS(Mutex& m) { m.lock(); } +#define SRT_ATTR_CAPABILITY(expr) +#define SRT_ATTR_SCOPED_CAPABILITY +#define SRT_ATTR_GUARDED_BY(expr) _Guarded_by_(expr) +#define SRT_ATTR_PT_GUARDED_BY(expr) +#define SRT_ATTR_ACQUIRED_BEFORE(...) +#define SRT_ATTR_ACQUIRED_AFTER(...) +#define SRT_ATTR_REQUIRES(expr) _Requires_lock_held_(expr) +#define SRT_ATTR_REQUIRES2(expr1, expr2) _Requires_lock_held_(expr1) _Requires_lock_held_(expr2) +#define SRT_ATTR_REQUIRES_SHARED(...) +#define SRT_ATTR_ACQUIRE(expr) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_ACQUIRE_SHARED(...) +#define SRT_ATTR_RELEASE(expr) _Releases_lock_(expr) +#define SRT_ATTR_RELEASE_SHARED(...) +#define SRT_ATTR_RELEASE_GENERIC(...) +#define SRT_ATTR_TRY_ACQUIRE(...) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) +#define SRT_ATTR_EXCLUDES(...) +#define SRT_ATTR_ASSERT_CAPABILITY(expr) +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) +#define SRT_ATTR_RETURN_CAPABILITY(x) +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS +#else + +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define SRT_ATTR_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SRT_ATTR_SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define SRT_ATTR_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define SRT_ATTR_PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define SRT_ATTR_ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES2(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_GENERIC(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define SRT_ATTR_ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define SRT_ATTR_RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // not _MSC_VER + +#endif // INC_SRT_ATTR_DEFS_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_compat.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_compat.h new file mode 100644 index 000000000..960c1b85a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/srt_compat.h @@ -0,0 +1,109 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_COMPAT_H +#define INC_SRT_COMPAT_H + +#include +#include + +#ifndef SRT_API +#ifdef _WIN32 + #ifndef __MINGW32__ + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) + #else + #define SRT_API __declspec(dllimport) + #endif + #else + #define SRT_API + #endif + #else + #define SRT_API + #endif +#else + #define SRT_API __attribute__ ((visibility("default"))) +#endif +#endif + +#ifdef _WIN32 + // https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "Id" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "Iu" + #endif +#else + // http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "zd" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "zu" + #endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Ensures that we store the error in the buffer and return the bufer. */ +SRT_API const char * SysStrError(int errnum, char * buf, size_t buflen); + +#ifdef __cplusplus +} // extern C + + +// Extra C++ stuff. Included only in C++ mode. + + +#include +#include +inline std::string SysStrError(int errnum) +{ + char buf[1024]; + return SysStrError(errnum, buf, 1024); +} + +inline struct tm SysLocalTime(time_t tt) +{ + struct tm tms; + memset(&tms, 0, sizeof tms); +#ifdef _WIN32 + errno_t rr = localtime_s(&tms, &tt); + if (rr == 0) + return tms; +#else + + // Ignore the error, state that if something + // happened, you simply have a pre-cleared tms. + localtime_r(&tt, &tms); +#endif + + return tms; +} + + +#endif // defined C++ + +#endif // INC_SRT_COMPAT_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/stats.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/stats.h new file mode 100644 index 000000000..bce60761b --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/stats.h @@ -0,0 +1,221 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_STATS_H +#define INC_SRT_STATS_H + +#include "platform_sys.h" +#include "packet.h" + +namespace srt +{ +namespace stats +{ + +class Packets +{ +public: + Packets() : m_count(0) {} + + Packets(uint32_t num) : m_count(num) {} + + void reset() + { + m_count = 0; + } + + Packets& operator+= (const Packets& other) + { + m_count += other.m_count; + return *this; + } + + uint32_t count() const + { + return m_count; + } + +private: + uint32_t m_count; +}; + +class BytesPackets +{ +public: + BytesPackets() + : m_bytes(0) + , m_packets(0) + {} + + BytesPackets(uint64_t bytes, uint32_t n = 1) + : m_bytes(bytes) + , m_packets(n) + {} + + BytesPackets& operator+= (const BytesPackets& other) + { + m_bytes += other.m_bytes; + m_packets += other.m_packets; + return *this; + } + +public: + void reset() + { + m_packets = 0; + m_bytes = 0; + } + + void count(uint64_t bytes, size_t n = 1) + { + m_packets += (uint32_t) n; + m_bytes += bytes; + } + + uint64_t bytes() const + { + return m_bytes; + } + + uint32_t count() const + { + return m_packets; + } + + uint64_t bytesWithHdr() const + { + return m_bytes + m_packets * CPacket::SRT_DATA_HDR_SIZE; + } + +private: + uint64_t m_bytes; + uint32_t m_packets; +}; + +template +struct Metric +{ + METRIC_TYPE trace; + METRIC_TYPE total; + + void count(METRIC_TYPE val) + { + trace += val; + total += val; + } + + void reset() + { + trace.reset(); + total.reset(); + } + + void resetTrace() + { + trace.reset(); + } +}; + +/// Sender-side statistics. +struct Sender +{ + Metric sent; + Metric sentUnique; + Metric sentRetrans; // The number of data packets retransmitted by the sender. + Metric lost; // The number of packets reported lost (including repeated reports) to the sender in NAKs. + Metric dropped; // The number of data packets dropped by the sender. + + Metric sentFilterExtra; // The number of packets generate by the packet filter and sent by the sender. + + Metric recvdAck; // The number of ACK packets received by the sender. + Metric recvdNak; // The number of ACK packets received by the sender. + + void reset() + { + sent.reset(); + sentUnique.reset(); + sentRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdAck.reset(); + recvdNak.reset(); + sentFilterExtra.reset(); + } + + void resetTrace() + { + sent.resetTrace(); + sentUnique.resetTrace(); + sentRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdAck.resetTrace(); + recvdNak.resetTrace(); + sentFilterExtra.resetTrace(); + } +}; + +/// Receiver-side statistics. +struct Receiver +{ + Metric recvd; + Metric recvdUnique; + Metric recvdRetrans; // The number of retransmitted data packets received by the receiver. + Metric lost; // The number of packets detected by the receiver as lost. + Metric dropped; // The number of packets dropped by the receiver (as too-late to be delivered). + Metric recvdBelated; // The number of belated packets received (dropped as too late but eventually received). + Metric undecrypted; // The number of packets received by the receiver that failed to be decrypted. + + Metric recvdFilterExtra; // The number of filter packets (e.g. FEC) received by the receiver. + Metric suppliedByFilter; // The number of lost packets got from the packet filter at the receiver side (e.g. loss recovered by FEC). + Metric lossFilter; // The number of lost DATA packets not recovered by the packet filter at the receiver side. + + Metric sentAck; // The number of ACK packets sent by the receiver. + Metric sentNak; // The number of NACK packets sent by the receiver. + + void reset() + { + recvd.reset(); + recvdUnique.reset(); + recvdRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdBelated.reset(); + undecrypted.reset(); + recvdFilterExtra.reset(); + suppliedByFilter.reset(); + lossFilter.reset(); + sentAck.reset(); + sentNak.reset(); + } + + void resetTrace() + { + recvd.resetTrace(); + recvdUnique.resetTrace(); + recvdRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdBelated.resetTrace(); + undecrypted.resetTrace(); + recvdFilterExtra.resetTrace(); + suppliedByFilter.resetTrace(); + lossFilter.resetTrace(); + sentAck.resetTrace(); + sentNak.resetTrace(); + } +}; + +} // namespace stats +} // namespace srt + +#endif // INC_SRT_STATS_H + + diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/sync.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/sync.h new file mode 100644 index 000000000..87be6f458 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/sync.h @@ -0,0 +1,947 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +#pragma once +#ifndef INC_SRT_SYNC_H +#define INC_SRT_SYNC_H + +#include "platform_sys.h" + +#include +#include +#ifdef ENABLE_STDCXX_SYNC +#include +#include +#include +#include +#include +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_STDCXX_STEADY +#define SRT_SYNC_CLOCK_STR "STDCXX_STEADY" +#else +#include + +// Defile clock type to use +#ifdef IA32 +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA32_RDTSC +#define SRT_SYNC_CLOCK_STR "IA32_RDTSC" +#elif defined(IA64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA64_ITC +#define SRT_SYNC_CLOCK_STR "IA64_ITC" +#elif defined(AMD64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_AMD64_RDTSC +#define SRT_SYNC_CLOCK_STR "AMD64_RDTSC" +#elif defined(_WIN32) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_WINQPC +#define SRT_SYNC_CLOCK_STR "WINQPC" +#elif TARGET_OS_MAC +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_MACH_ABSTIME +#define SRT_SYNC_CLOCK_STR "MACH_ABSTIME" +#elif defined(ENABLE_MONOTONIC_CLOCK) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_GETTIME_MONOTONIC +#define SRT_SYNC_CLOCK_STR "GETTIME_MONOTONIC" +#else +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY +#define SRT_SYNC_CLOCK_STR "POSIX_GETTIMEOFDAY" +#endif + +#endif // ENABLE_STDCXX_SYNC + +#include "srt.h" +#include "utilities.h" +#include "srt_attr_defs.h" + + +namespace srt +{ + +class CUDTException; // defined in common.h + +namespace sync +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration class +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +template +using Duration = std::chrono::duration; + +#else + +/// Class template srt::sync::Duration represents a time interval. +/// It consists of a count of ticks of _Clock. +/// It is a wrapper of system timers in case of non-C++11 chrono build. +template +class Duration +{ +public: + Duration() + : m_duration(0) + { + } + + explicit Duration(int64_t d) + : m_duration(d) + { + } + +public: + inline int64_t count() const { return m_duration; } + + static Duration zero() { return Duration(); } + +public: // Relational operators + inline bool operator>=(const Duration& rhs) const { return m_duration >= rhs.m_duration; } + inline bool operator>(const Duration& rhs) const { return m_duration > rhs.m_duration; } + inline bool operator==(const Duration& rhs) const { return m_duration == rhs.m_duration; } + inline bool operator!=(const Duration& rhs) const { return m_duration != rhs.m_duration; } + inline bool operator<=(const Duration& rhs) const { return m_duration <= rhs.m_duration; } + inline bool operator<(const Duration& rhs) const { return m_duration < rhs.m_duration; } + +public: // Assignment operators + inline void operator*=(const int64_t mult) { m_duration = static_cast(m_duration * mult); } + inline void operator+=(const Duration& rhs) { m_duration += rhs.m_duration; } + inline void operator-=(const Duration& rhs) { m_duration -= rhs.m_duration; } + + inline Duration operator+(const Duration& rhs) const { return Duration(m_duration + rhs.m_duration); } + inline Duration operator-(const Duration& rhs) const { return Duration(m_duration - rhs.m_duration); } + inline Duration operator*(const int64_t& rhs) const { return Duration(m_duration * rhs); } + inline Duration operator/(const int64_t& rhs) const { return Duration(m_duration / rhs); } + +private: + // int64_t range is from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 + int64_t m_duration; +}; + +#endif // ENABLE_STDCXX_SYNC + +/////////////////////////////////////////////////////////////////////////////// +// +// TimePoint and steadt_clock classes +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +using steady_clock = std::chrono::steady_clock; + +template +using time_point = std::chrono::time_point; + +template +using TimePoint = std::chrono::time_point; + +template +inline bool is_zero(const time_point &tp) +{ + return tp.time_since_epoch() == Clock::duration::zero(); +} + +inline bool is_zero(const steady_clock::time_point& t) +{ + return t == steady_clock::time_point(); +} + +#else +template +class TimePoint; + +class steady_clock +{ +public: + typedef Duration duration; + typedef TimePoint time_point; + +public: + static time_point now(); +}; + +/// Represents a point in time +template +class TimePoint +{ +public: + TimePoint() + : m_timestamp(0) + { + } + + explicit TimePoint(uint64_t tp) + : m_timestamp(tp) + { + } + + TimePoint(const TimePoint& other) + : m_timestamp(other.m_timestamp) + { + } + + TimePoint(const Duration& duration_since_epoch) + : m_timestamp(duration_since_epoch.count()) + { + } + + ~TimePoint() {} + +public: // Relational operators + inline bool operator<(const TimePoint& rhs) const { return m_timestamp < rhs.m_timestamp; } + inline bool operator<=(const TimePoint& rhs) const { return m_timestamp <= rhs.m_timestamp; } + inline bool operator==(const TimePoint& rhs) const { return m_timestamp == rhs.m_timestamp; } + inline bool operator!=(const TimePoint& rhs) const { return m_timestamp != rhs.m_timestamp; } + inline bool operator>=(const TimePoint& rhs) const { return m_timestamp >= rhs.m_timestamp; } + inline bool operator>(const TimePoint& rhs) const { return m_timestamp > rhs.m_timestamp; } + +public: // Arithmetic operators + inline Duration operator-(const TimePoint& rhs) const + { + return Duration(m_timestamp - rhs.m_timestamp); + } + inline TimePoint operator+(const Duration& rhs) const { return TimePoint(m_timestamp + rhs.count()); } + inline TimePoint operator-(const Duration& rhs) const { return TimePoint(m_timestamp - rhs.count()); } + +public: // Assignment operators + inline void operator=(const TimePoint& rhs) { m_timestamp = rhs.m_timestamp; } + inline void operator+=(const Duration& rhs) { m_timestamp += rhs.count(); } + inline void operator-=(const Duration& rhs) { m_timestamp -= rhs.count(); } + +public: // + static inline ATR_CONSTEXPR TimePoint min() { return TimePoint(std::numeric_limits::min()); } + static inline ATR_CONSTEXPR TimePoint max() { return TimePoint(std::numeric_limits::max()); } + +public: + Duration time_since_epoch() const; + +private: + uint64_t m_timestamp; +}; + +template <> +srt::sync::Duration srt::sync::TimePoint::time_since_epoch() const; + +inline Duration operator*(const int& lhs, const Duration& rhs) +{ + return rhs * lhs; +} + +#endif // ENABLE_STDCXX_SYNC + +// NOTE: Moved the following class definitions to "atomic_clock.h" +// template +// class AtomicDuration; +// template +// class AtomicClock; + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration and timepoint conversions +// +/////////////////////////////////////////////////////////////////////////////// + +/// Function return number of decimals in a subsecond precision. +/// E.g. for a microsecond accuracy of steady_clock the return would be 6. +/// For a nanosecond accuracy of the steady_clock the return value would be 9. +int clockSubsecondPrecision(); + +#if ENABLE_STDCXX_SYNC + +inline long long count_microseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_microseconds(const steady_clock::time_point tp) +{ + return std::chrono::duration_cast(tp.time_since_epoch()).count(); +} + +inline long long count_milliseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_seconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline steady_clock::duration microseconds_from(int64_t t_us) +{ + return std::chrono::microseconds(t_us); +} + +inline steady_clock::duration milliseconds_from(int64_t t_ms) +{ + return std::chrono::milliseconds(t_ms); +} + +inline steady_clock::duration seconds_from(int64_t t_s) +{ + return std::chrono::seconds(t_s); +} + +#else + +int64_t count_microseconds(const steady_clock::duration& t); +int64_t count_milliseconds(const steady_clock::duration& t); +int64_t count_seconds(const steady_clock::duration& t); + +Duration microseconds_from(int64_t t_us); +Duration milliseconds_from(int64_t t_ms); +Duration seconds_from(int64_t t_s); + +inline bool is_zero(const TimePoint& t) +{ + return t == TimePoint(); +} + +#endif // ENABLE_STDCXX_SYNC + + +/////////////////////////////////////////////////////////////////////////////// +// +// Mutex section +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC +using Mutex = std::mutex; +using UniqueLock = std::unique_lock; +using ScopedLock = std::lock_guard; +#else +/// Mutex is a class wrapper, that should mimic the std::chrono::mutex class. +/// At the moment the extra function ref() is temporally added to allow calls +/// to pthread_cond_timedwait(). Will be removed by introducing CEvent. +class SRT_ATTR_CAPABILITY("mutex") Mutex +{ + friend class SyncEvent; + +public: + Mutex(); + ~Mutex(); + +public: + int lock() SRT_ATTR_ACQUIRE(); + int unlock() SRT_ATTR_RELEASE(); + + /// @return true if the lock was acquired successfully, otherwise false + bool try_lock() SRT_ATTR_TRY_ACQUIRE(true); + + // TODO: To be removed with introduction of the CEvent. + pthread_mutex_t& ref() { return m_mutex; } + +private: + pthread_mutex_t m_mutex; +}; + +/// A pthread version of std::chrono::scoped_lock (or lock_guard for C++11) +class SRT_ATTR_SCOPED_CAPABILITY ScopedLock +{ +public: + SRT_ATTR_ACQUIRE(m) + explicit ScopedLock(Mutex& m); + + SRT_ATTR_RELEASE() + ~ScopedLock(); + +private: + Mutex& m_mutex; +}; + +/// A pthread version of std::chrono::unique_lock +class SRT_ATTR_SCOPED_CAPABILITY UniqueLock +{ + friend class SyncEvent; + int m_iLocked; + Mutex& m_Mutex; + +public: + SRT_ATTR_ACQUIRE(m) + explicit UniqueLock(Mutex &m); + + SRT_ATTR_RELEASE() + ~UniqueLock(); + +public: + SRT_ATTR_ACQUIRE() + void lock(); + + SRT_ATTR_RELEASE() + void unlock(); + + SRT_ATTR_RETURN_CAPABILITY(m_Mutex) + Mutex* mutex(); // reflects C++11 unique_lock::mutex() +}; +#endif // ENABLE_STDCXX_SYNC + +inline void enterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) { m.lock(); } + +inline bool tryEnterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_TRY_ACQUIRE(true, m) { return m.try_lock(); } + +inline void leaveCS(Mutex& m) SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) { m.unlock(); } + +class InvertedLock +{ + Mutex& m_mtx; + +public: + SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) + InvertedLock(Mutex& m) + : m_mtx(m) + { + m_mtx.unlock(); + } + + SRT_ATTR_ACQUIRE(m_mtx) + ~InvertedLock() + { + m_mtx.lock(); + } +}; + +inline void setupMutex(Mutex&, const char*) {} +inline void releaseMutex(Mutex&) {} + +//////////////////////////////////////////////////////////////////////////////// +// +// Condition section +// +//////////////////////////////////////////////////////////////////////////////// + +class Condition +{ +public: + Condition(); + ~Condition(); + +public: + /// These functions do not align with C++11 version. They are here hopefully as a temporal solution + /// to avoud issues with static initialization of CV on windows. + void init(); + void destroy(); + +public: + /// Causes the current thread to block until the condition variable is notified + /// or a spurious wakeup occurs. + /// + /// @param lock Corresponding mutex locked by UniqueLock + void wait(UniqueLock& lock); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on *this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. When unblocked, regardless of the reason, + /// lock is reacquired and wait_for() exits. + /// + /// @returns false if the relative timeout specified by rel_time expired, + /// true otherwise (signal or spurious wake up). + /// + /// @note Calling this function if lock.mutex() + /// is not locked by the current thread is undefined behavior. + /// Calling this function if lock.mutex() is not the same mutex as the one + /// used by all other threads that are currently waiting on the same + /// condition variable is undefined behavior. + bool wait_for(UniqueLock& lock, const steady_clock::duration& rel_time); + + /// Causes the current thread to block until the condition variable is notified, + /// a specific time is reached, or a spurious wakeup occurs. + /// + /// @param[in] lock an object of type UniqueLock, which must be locked by the current thread + /// @param[in] timeout_time an object of type time_point representing the time when to stop waiting + /// + /// @returns false if the relative timeout specified by timeout_time expired, + /// true otherwise (signal or spurious wake up). + bool wait_until(UniqueLock& lock, const steady_clock::time_point& timeout_time); + + /// Calling notify_one() unblocks one of the waiting threads, + /// if any threads are waiting on this CV. + void notify_one(); + + /// Unblocks all threads currently waiting for this CV. + void notify_all(); + +private: +#if ENABLE_STDCXX_SYNC + std::condition_variable m_cv; +#else + pthread_cond_t m_cv; +#endif +}; + +inline void setupCond(Condition& cv, const char*) { cv.init(); } +inline void releaseCond(Condition& cv) { cv.destroy(); } + +/////////////////////////////////////////////////////////////////////////////// +// +// Event (CV) section +// +/////////////////////////////////////////////////////////////////////////////// + +// This class is used for condition variable combined with mutex by different ways. +// This should provide a cleaner API around locking with debug-logging inside. +class CSync +{ +protected: + Condition* m_cond; + UniqueLock* m_locker; + +public: + // Locked version: must be declared only after the declaration of UniqueLock, + // which has locked the mutex. On this delegate you should call only + // signal_locked() and pass the UniqueLock variable that should remain locked. + // Also wait() and wait_for() can be used only with this socket. + CSync(Condition& cond, UniqueLock& g) + : m_cond(&cond), m_locker(&g) + { + // XXX it would be nice to check whether the owner is also current thread + // but this can't be done portable way. + + // When constructed by this constructor, the user is expected + // to only call signal_locked() function. You should pass the same guard + // variable that you have used for construction as its argument. + } + + // COPY CONSTRUCTOR: DEFAULT! + + // Wait indefinitely, until getting a signal on CV. + void wait() + { + m_cond->wait(*m_locker); + } + + /// Block the call until either @a timestamp time achieved + /// or the conditional is signaled. + /// @param [in] delay Maximum time to wait since the moment of the call + /// @retval false if the relative timeout specified by rel_time expired, + /// @retval true if condition is signaled or spurious wake up. + bool wait_for(const steady_clock::duration& delay) + { + return m_cond->wait_for(*m_locker, delay); + } + + // Wait until the given time is achieved. + /// @param [in] exptime The target time to wait until. + /// @retval false if the target wait time is reached. + /// @retval true if condition is signal or spurious wake up. + bool wait_until(const steady_clock::time_point& exptime) + { + return m_cond->wait_until(*m_locker, exptime); + } + + // Static ad-hoc version + static void lock_notify_one(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_one(); + } + + static void lock_notify_all(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_all(); + } + + void notify_one_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_one(); + } + + void notify_all_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_all(); + } + + // The *_relaxed functions are to be used in case when you don't care + // whether the associated mutex is locked or not (you accept the case that + // a mutex isn't locked and the condition notification gets effectively + // missed), or you somehow know that the mutex is locked, but you don't + // have access to the associated UniqueLock object. This function, although + // it does the same thing as CSync::notify_one_locked etc. here for the + // user to declare explicitly that notifying is done without being + // prematurely certain that the associated mutex is locked. + // + // It is then expected that whenever these functions are used, an extra + // comment is provided to explain, why the use of the relaxed notification + // is correctly used. + + void notify_one_relaxed() { notify_one_relaxed(*m_cond); } + static void notify_one_relaxed(Condition& cond) { cond.notify_one(); } + static void notify_all_relaxed(Condition& cond) { cond.notify_all(); } +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +// XXX Do not use this class now, there's an unknown issue +// connected to object management with the use of release* functions. +// Until this is solved, stay with separate *Cond and *Lock fields. +class CEvent +{ +public: + CEvent(); + ~CEvent(); + +public: + Mutex& mutex() { return m_lock; } + Condition& cond() { return m_cond; } + +public: + /// Causes the current thread to block until + /// a specific time is reached. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_until(const steady_clock::time_point& tp); + + /// Blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// Uses internal mutex to lock. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_for(const steady_clock::duration& rel_time); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// When unblocked, regardless of the reason, lock is reacquiredand wait_for() exits. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool wait_for(UniqueLock& lk, const steady_clock::duration& rel_time); + + void lock_wait(); + + void wait(UniqueLock& lk); + + void notify_one(); + + void notify_all(); + + void lock_notify_one() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_one(); + } + + void lock_notify_all() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_all(); + } + +private: + Mutex m_lock; + Condition m_cond; +}; + + +// This class binds together the functionality of +// UniqueLock and CSync. It provides a simple interface of CSync +// while having already the UniqueLock applied in the scope, +// so a safe statement can be made about the mutex being locked +// when signalling or waiting. +class CUniqueSync: public CSync +{ + UniqueLock m_ulock; + +public: + + UniqueLock& locker() { return m_ulock; } + + CUniqueSync(Mutex& mut, Condition& cnd) + : CSync(cnd, m_ulock) + , m_ulock(mut) + { + } + + CUniqueSync(CEvent& event) + : CSync(event.cond(), m_ulock) + , m_ulock(event.mutex()) + { + } + + // These functions can be used safely because + // this whole class guarantees that whatever happens + // while its object exists is that the mutex is locked. + + void notify_one() + { + m_cond->notify_one(); + } + + void notify_all() + { + m_cond->notify_all(); + } +}; + +class CTimer +{ +public: + CTimer(); + ~CTimer(); + +public: + /// Causes the current thread to block until + /// the specified time is reached. + /// Sleep can be interrupted by calling interrupt() + /// or woken up to recheck the scheduled time by tick() + /// @param tp target time to sleep until + /// + /// @return true if the specified time was reached + /// false should never happen + bool sleep_until(steady_clock::time_point tp); + + /// Resets target wait time and interrupts waiting + /// in sleep_until(..) + void interrupt(); + + /// Wakes up waiting thread (sleep_until(..)) without + /// changing the target waiting time to force a recheck + /// of the current time in comparisson to the target time. + void tick(); + +private: + CEvent m_event; + steady_clock::time_point m_tsSchedTime; +}; + + +/// Print steady clock timepoint in a human readable way. +/// days HH:MM:SS.us [STD] +/// Example: 1D 02:12:56.123456 +/// +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTime(const steady_clock::time_point& time); + +/// Print steady clock timepoint relative to the current system time +/// Date HH:MM:SS.us [SYS] +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTimeSys(const steady_clock::time_point& time); + +enum eDurationUnit {DUNIT_S, DUNIT_MS, DUNIT_US}; + +template +struct DurationUnitName; + +template<> +struct DurationUnitName +{ + static const char* name() { return "us"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur)); } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "ms"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000.0; } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "s"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000000.0; } +}; + +template +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return Sprint(DurationUnitName::count(dur)) + DurationUnitName::name(); +} + +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return FormatDuration(dur); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// CGlobEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +class CGlobEvent +{ +public: + /// Triggers the event and notifies waiting threads. + /// Simply calls notify_one(). + static void triggerEvent(); + + /// Waits for the event to be triggered with 10ms timeout. + /// Simply calls wait_for(). + static bool waitForEvent(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CThread class +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef ENABLE_STDCXX_SYNC +typedef std::system_error CThreadException; +using CThread = std::thread; +namespace this_thread = std::this_thread; +#else // pthreads wrapper version +typedef CUDTException CThreadException; + +class CThread +{ +public: + CThread(); + /// @throws std::system_error if the thread could not be started. + CThread(void *(*start_routine) (void *), void *arg); + +#if HAVE_FULL_CXX11 + CThread& operator=(CThread &other) = delete; + CThread& operator=(CThread &&other); +#else + CThread& operator=(CThread &other); + /// To be used only in StartThread function. + /// Creates a new stread and assigns to this. + /// @throw CThreadException + void create_thread(void *(*start_routine) (void *), void *arg); +#endif + +public: // Observers + /// Checks if the CThread object identifies an active thread of execution. + /// A default constructed thread is not joinable. + /// A thread that has finished executing code, but has not yet been joined + /// is still considered an active thread of execution and is therefore joinable. + bool joinable() const; + + struct id + { + explicit id(const pthread_t t) + : value(t) + {} + + const pthread_t value; + inline bool operator==(const id& second) const + { + return pthread_equal(value, second.value) != 0; + } + }; + + /// Returns the id of the current thread. + /// In this implementation the ID is the pthread_t. + const id get_id() const { return id(m_thread); } + +public: + /// Blocks the current thread until the thread identified by *this finishes its execution. + /// If that thread has already terminated, then join() returns immediately. + /// + /// @throws std::system_error if an error occurs + void join(); + +public: // Internal + /// Calls pthread_create, throws exception on failure. + /// @throw CThreadException + void create(void *(*start_routine) (void *), void *arg); + +private: + pthread_t m_thread; +}; + +template +inline Stream& operator<<(Stream& str, const CThread::id& cid) +{ +#if defined(_WIN32) && (defined(PTW32_VERSION) || defined (__PTW32_VERSION)) + // This is a version specific for pthread-win32 implementation + // Here pthread_t type is a structure that is not convertible + // to a number at all. + return str << pthread_getw32threadid_np(cid.value); +#else + return str << cid.value; +#endif +} + +namespace this_thread +{ + const inline CThread::id get_id() { return CThread::id (pthread_self()); } + + inline void sleep_for(const steady_clock::duration& t) + { +#if !defined(_WIN32) + usleep(count_microseconds(t)); // microseconds +#else + Sleep((DWORD) count_milliseconds(t)); +#endif + } +} + +#endif + +/// StartThread function should be used to do CThread assignments: +/// @code +/// CThread a(); +/// a = CThread(func, args); +/// @endcode +/// +/// @returns true if thread was started successfully, +/// false on failure +/// +#ifdef ENABLE_STDCXX_SYNC +typedef void* (&ThreadFunc) (void*); +bool StartThread(CThread& th, ThreadFunc&& f, void* args, const std::string& name); +#else +bool StartThread(CThread& th, void* (*f) (void*), void* args, const std::string& name); +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// CThreadError class - thread local storage wrapper +// +//////////////////////////////////////////////////////////////////////////////// + +/// Set thread local error +/// @param e new CUDTException +void SetThreadLocalError(const CUDTException& e); + +/// Get thread local error +/// @returns CUDTException pointer +CUDTException& GetThreadLocalError(); + +//////////////////////////////////////////////////////////////////////////////// +// +// Random distribution functions. +// +//////////////////////////////////////////////////////////////////////////////// + +/// Generate a uniform-distributed random integer from [minVal; maxVal]. +/// If HAVE_CXX11, uses std::uniform_distribution(std::random_device). +/// @param[in] minVal minimum allowed value of the resulting random number. +/// @param[in] maxVal maximum allowed value of the resulting random number. +int genRandomInt(int minVal, int maxVal); + +} // namespace sync +} // namespace srt + +#include "atomic_clock.h" + +#endif // INC_SRT_SYNC_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/threadname.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/threadname.h new file mode 100644 index 000000000..1c064c86c --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/threadname.h @@ -0,0 +1,224 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_THREADNAME_H +#define INC_SRT_THREADNAME_H + +// NOTE: +// HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_GETNAME_NP +// HAVE_PTHREAD_GETNAME_NP +// Are detected and set in ../CMakeLists.txt. +// OS Availability of pthread_getname_np(..) and pthread_setname_np(..):: +// MacOS(10.6) +// iOS(3.2) +// AIX(7.1) +// FreeBSD(version?), OpenBSD(Version?) +// Linux-GLIBC(GLIBC-2.12). +// Linux-MUSL(MUSL-1.1.20 Partial Implementation. See below). +// MINGW-W64(4.0.6) + +#if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + || defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + #include + #if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_GETNAME_NP) + #define HAVE_PTHREAD_GETNAME_NP 1 + #endif + #if defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_SETNAME_NP) + #define HAVE_PTHREAD_SETNAME_NP 1 + #endif +#endif + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + // NOTE: + // Linux pthread_getname_np() and pthread_setname_np() became available + // in GLIBC-2.12 and later. + // Some Linux runtimes do not have pthread_getname_np(), but have + // pthread_setname_np(), for instance MUSL at least as of v1.1.20. + // So using the prctl() for Linux is more portable. + #if defined(__linux__) + #include + #endif + #include +#endif + +#include +#include +#include + +#include "common.h" +#include "sync.h" + +namespace srt { + +class ThreadName +{ + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + + class ThreadNameImpl + { + public: + static const size_t BUFSIZE = 64; + static const bool DUMMY_IMPL = false; + + static bool get(char* namebuf) + { +#if defined(__linux__) + // since Linux 2.6.11. The buffer should allow space for up to 16 + // bytes; the returned string will be null-terminated. + return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_GETNAME_NP) + return pthread_getname_np(pthread_self(), namebuf, BUFSIZE) == 0; +#else +#error "unsupported platform" +#endif + } + + static bool set(const char* name) + { + SRT_ASSERT(name != NULL); +#if defined(__linux__) + // The name can be up to 16 bytes long, including the terminating + // null byte. (If the length of the string, including the terminating + // null byte, exceeds 16 bytes, the string is silently truncated.) + return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_SETNAME_NP) + #if defined(__APPLE__) + return pthread_setname_np(name) == 0; + #else + return pthread_setname_np(pthread_self(), name) == 0; + #endif +#else +#error "unsupported platform" +#endif + } + + explicit ThreadNameImpl(const std::string& name) + : reset(false) + { + tid = pthread_self(); + + if (!get(old_name)) + return; + + reset = set(name.c_str()); + if (reset) + return; + + // Try with a shorter name. 15 is the upper limit supported by Linux, + // other platforms should support a larger value. So 15 should works + // on all platforms. + const size_t max_len = 15; + if (name.size() > max_len) + reset = set(name.substr(0, max_len).c_str()); + } + + ~ThreadNameImpl() + { + if (!reset) + return; + + // ensure it's called on the right thread + if (tid == pthread_self()) + set(old_name); + } + + private: + ThreadNameImpl(ThreadNameImpl& other); + ThreadNameImpl& operator=(const ThreadNameImpl& other); + + private: + bool reset; + pthread_t tid; + char old_name[BUFSIZE]; + }; + +#else + + class ThreadNameImpl + { + public: + static const bool DUMMY_IMPL = true; + static const size_t BUFSIZE = 64; + + static bool get(char* output) + { + // The default implementation will simply try to get the thread ID + std::ostringstream bs; + bs << "T" << sync::this_thread::get_id(); + size_t s = bs.str().copy(output, BUFSIZE - 1); + output[s] = '\0'; + return true; + } + + static bool set(const char*) { return false; } + + ThreadNameImpl(const std::string&) {} + + ~ThreadNameImpl() // just to make it "non-trivially-destructible" for compatibility with normal version + { + } + }; + +#endif // platform dependent impl + + // Why delegate to impl: + // 1. to make sure implementation on different platforms have the same interface. + // 2. it's simple to add some wrappers like get(const std::string &). + ThreadNameImpl impl; + +public: + static const bool DUMMY_IMPL = ThreadNameImpl::DUMMY_IMPL; + static const size_t BUFSIZE = ThreadNameImpl::BUFSIZE; + + /// @brief Print thread ID to the provided buffer. + /// The size of the destination buffer is assumed to be at least ThreadName::BUFSIZE. + /// @param [out] output destination buffer to get thread name + /// @return true on success, false on failure + static bool get(char* output) { + return ThreadNameImpl::get(output); + } + + static bool get(std::string& name) + { + char buf[BUFSIZE]; + bool ret = get(buf); + if (ret) + name = buf; + return ret; + } + + static bool set(const std::string& name) { return ThreadNameImpl::set(name.c_str()); } + + explicit ThreadName(const std::string& name) + : impl(name) + { + } + +private: + ThreadName(const ThreadName&); + ThreadName(const char*); + ThreadName& operator=(const ThreadName& other); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/tsbpd_time.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/tsbpd_time.h new file mode 100644 index 000000000..3483c197f --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/tsbpd_time.h @@ -0,0 +1,163 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_TSBPD_TIME_H +#define INC_SRT_TSBPD_TIME_H + +#include "platform_sys.h" +#include "sync.h" +#include "utilities.h" + +namespace srt +{ + +/// @brief TimeStamp-Based Packet Delivery Mode (TSBPD) time conversion logic. +/// Used by the receiver to calculate delivery time of data packets. +/// See SRT Internet Draft Section "Timestamp-Based Packet Delivery". +class CTsbpdTime +{ + typedef srt::sync::steady_clock steady_clock; + typedef steady_clock::time_point time_point; + typedef steady_clock::duration duration; + typedef srt::sync::Mutex Mutex; + +public: + CTsbpdTime() + : m_iFirstRTT(-1) + , m_bTsbPdMode(false) + , m_tdTsbPdDelay(0) + , m_bTsbPdWrapCheck(false) + { + } + + /// Set TimeStamp-Based Packet Delivery Mode (receiver). + /// @param [in] timebase local time base (uSec) of packet time stamps including buffering delay. + /// @param [in] wrap wrapping period. + /// @param [in] delay negotiated TsbPD delay (buffering latency). + void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); + + /// @brief Check if TSBPD logic is enabled. + /// @return true if TSBPD is enabled. + bool isEnabled() const { return m_bTsbPdMode; } + + /// @brief Apply new state derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp wrap period (enabled or not). + /// @param delay TSBPD delay. + /// @param udrift clock drift. + void applyGroupTime(const time_point& timebase, bool wrp, uint32_t delay, const duration& udrift); + + /// @brief Apply new clock state (TSBPD base and drift) derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp state of the wrapping period (enabled or disabled). + /// @param udrift clock drift. + void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift); + + /// @brief Add new drift sample from an ACK-ACKACK pair. + /// ACKACK packets are sent immediately (except for UDP buffering). + /// Therefore their timestamp roughly corresponds to the time of sending + /// and can be used to estimate clock drift. + /// + /// @param [in] pktTimestamp Timestamp of the arrived ACKACK packet. + /// @param [in] tsPktArrival packet arrival time. + /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. If no sample, pass '-1'. + /// + /// @return true if TSBPD base time has changed, false otherwise. + bool addDriftSample(uint32_t pktTimestamp, const time_point& tsPktArrival, int usRTTSample); + + /// @brief Handle timestamp of data packet when 32-bit integer carryover is about to happen. + /// When packet timestamp approaches CPacket::MAX_TIMESTAMP, the TSBPD base time should be + /// shifted accordingly to correctly handle new packets with timestamps starting from zero. + /// @param usPktTimestamp timestamp field value of a data packet. + void updateTsbPdTimeBase(uint32_t usPktTimestamp); + + /// @brief Get TSBPD base time adjusted for carryover, which occurs when + /// a packet's timestamp exceeds the UINT32_MAX and continues from zero. + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return TSBPD base time for a provided packet timestamp. + time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time without buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application. + /// Essentially: getTsbPdTimeBase(usPktTimestamp) + usPktTimestamp + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD base time without buffering delay. + time_point getPktTsbPdBaseTime(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time with buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application + /// (including drift and carryover effects, if any). + /// Essentially: getPktTsbPdBaseTime(usPktTimestamp) + m_tdTsbPdDelay + drift() + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD time with buffering delay. + time_point getPktTsbPdTime(uint32_t usPktTimestamp) const; + + /// @brief Get current drift value. + /// @return current drift value. + int64_t drift() const { return m_DriftTracer.drift(); } + + /// @brief Get current overdrift value. + /// @return current overdrift value. + int64_t overdrift() const { return m_DriftTracer.overdrift(); } + + /// @brief Get internal state to apply to another member of a socket group. + /// @param w_tb TsbPd base time. + /// @param w_udrift drift value. + /// @param w_wrp wrap check. + void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift) const; + +private: + int m_iFirstRTT; // First measured RTT sample. + bool m_bTsbPdMode; // Receiver buffering and TSBPD is active when true. + duration m_tdTsbPdDelay; // Negotiated buffering delay. + + /// @brief Local time base for TsbPd. + /// @note m_tsTsbPdTimeBase is changed in the following cases: + /// 1. Initialized upon SRT_CMD_HSREQ packet as the difference with the current time: + /// = (NOW - PACKET_TIMESTAMP), at the time of HSREQ reception. + /// 2. Shifted forward on timestamp overflow (@see CTsbpdTime::updateTsbPdTimeBase), when overflow + /// of the timestamp field value of a data packet is detected. + /// += CPacket::MAX_TIMESTAMP + 1 + /// 3. Clock drift (@see CTsbpdTime::addDriftSample, executed exclusively + /// from ACKACK handler). This is updated with (positive or negative) TSBPD_DRIFT_MAX_VALUE + /// once the value of average drift exceeds this value in either direction. + /// += (+/-)TSBPD_DRIFT_MAX_VALUE + /// + /// @note The TSBPD base time is expected to hold the following condition: + /// (PACKET_TIMESTAMP + m_tsTsbPdTimeBase + drift) == NOW. + /// Then it can be used to estimate the origin time of a data packet, and calculate its delivery time + /// with buffering delay applied. + time_point m_tsTsbPdTimeBase; + + /// @note Packet timestamps wrap around every 01h11m35s (32-bit in usec). + /// A wrap check period starts 30 seconds (TSBPD_WRAP_PERIOD) before the wrap point. + /// During the wrap check period, packet timestamps smaller than 30 seconds + /// are considered to have been wrapped around. + /// The wrap check period ends 30 seconds after the wrap point, + /// after which the TSBPD base time is adjusted. + bool m_bTsbPdWrapCheck; // true: check packet time stamp wraparound (overflow). + static const uint32_t TSBPD_WRAP_PERIOD = (30 * 1000000); // 30 seconds (in usec) for timestamp wrapping period. + + /// Maximum clock drift (microseconds) above which TsbPD base time is already adjusted. + static const int TSBPD_DRIFT_MAX_VALUE = 5000; + /// Number of samples (ACKACK packets) on which to perform drift calculation and compensation. + static const int TSBPD_DRIFT_MAX_SAMPLES = 1000; + DriftTracer m_DriftTracer; + + /// Protect simultaneous change of state (read/write). + mutable Mutex m_mtxRW; +}; + +} // namespace srt + +#endif // INC_SRT_TSBPD_TIME_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/udt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/udt.h index 77f903bd5..ee4c02f4d 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/udt.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/udt.h @@ -64,16 +64,16 @@ modified by * file doesn't contain _FUNCTIONS_ predicted to be used in C - see udtc.h */ -#ifndef __UDT_H__ -#define __UDT_H__ +#ifndef INC_SRT_UDT_H +#define INC_SRT_UDT_H #include "srt.h" /* -* SRT_ENABLE_THREADCHECK (THIS IS SET IN MAKEFILE NOT HERE) +* SRT_ENABLE_THREADCHECK IS SET IN MAKEFILE, NOT HERE */ #if defined(SRT_ENABLE_THREADCHECK) -#include +#include "threadcheck.h" #else #define THREAD_STATE_INIT(name) #define THREAD_EXIT() @@ -82,13 +82,6 @@ modified by #define INCREMENT_THREAD_ITERATIONS() #endif -/* Obsolete way to define MINGW */ -#ifndef __MINGW__ -#if defined(__MINGW32__) || defined(__MINGW64__) -#define __MINGW__ 1 -#endif -#endif - #ifdef __cplusplus #include #include @@ -96,10 +89,6 @@ modified by #include #endif - -// Legacy/backward/deprecated -#define UDT_API SRT_API - //////////////////////////////////////////////////////////////////////////////// //if compiling on VC6.0 or pre-WindowsXP systems @@ -108,83 +97,6 @@ modified by //if compiling with MinGW, it only works on XP or above //use -D_WIN32_WINNT=0x0501 - -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -// This facility is used only for select() function. -// This is considered obsolete and the epoll() functionality rather should be used. -typedef std::set ud_set; -#define UD_CLR(u, uset) ((uset)->erase(u)) -#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) -#define UD_SET(u, uset) ((uset)->insert(u)) -#define UD_ZERO(uset) ((uset)->clear()) -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Legacy names - -#define UDT_MSS SRTO_MSS -#define UDT_SNDSYN SRTO_SNDSYN -#define UDT_RCVSYN SRTO_RCVSYN -#define UDT_FC SRTO_FC -#define UDT_SNDBUF SRTO_SNDBUF -#define UDT_RCVBUF SRTO_RCVBUF -#define UDT_LINGER SRTO_LINGER -#define UDP_SNDBUF SRTO_UDP_SNDBUF -#define UDP_RCVBUF SRTO_UDP_RCVBUF -#define UDT_MAXMSG SRTO_MAXMSG -#define UDT_MSGTTL SRTO_MSGTTL -#define UDT_RENDEZVOUS SRTO_RENDEZVOUS -#define UDT_SNDTIMEO SRTO_SNDTIMEO -#define UDT_RCVTIMEO SRTO_RCVTIMEO -#define UDT_REUSEADDR SRTO_REUSEADDR -#define UDT_MAXBW SRTO_MAXBW -#define UDT_STATE SRTO_STATE -#define UDT_EVENT SRTO_EVENT -#define UDT_SNDDATA SRTO_SNDDATA -#define UDT_RCVDATA SRTO_RCVDATA -#define SRT_SENDER SRTO_SENDER -#define SRT_TSBPDMODE SRTO_TSBPDMODE -#define SRT_TSBPDDELAY SRTO_TSBPDDELAY -#define SRT_INPUTBW SRTO_INPUTBW -#define SRT_OHEADBW SRTO_OHEADBW -#define SRT_PASSPHRASE SRTO_PASSPHRASE -#define SRT_PBKEYLEN SRTO_PBKEYLEN -#define SRT_KMSTATE SRTO_KMSTATE -#define SRT_IPTTL SRTO_IPTTL -#define SRT_IPTOS SRTO_IPTOS -#define SRT_TLPKTDROP SRTO_TLPKTDROP -#define SRT_TSBPDMAXLAG SRTO_TSBPDMAXLAG -#define SRT_RCVNAKREPORT SRTO_NAKREPORT -#define SRT_CONNTIMEO SRTO_CONNTIMEO -#define SRT_SNDPBKEYLEN SRTO_SNDPBKEYLEN -#define SRT_RCVPBKEYLEN SRTO_RCVPBKEYLEN -#define SRT_SNDPEERKMSTATE SRTO_SNDPEERKMSTATE -#define SRT_RCVKMSTATE SRTO_RCVKMSTATE - -#define UDT_EPOLL_OPT SRT_EPOLL_OPT -#define UDT_EPOLL_IN SRT_EPOLL_IN -#define UDT_EPOLL_OUT SRT_EPOLL_OUT -#define UDT_EPOLL_ERR SRT_EPOLL_ERR - -/* Binary backward compatibility obsolete options */ -#define SRT_NAKREPORT SRT_RCVNAKREPORT - -#if !defined(SRT_DISABLE_LEGACY_UDTSTATUS) -#define UDTSTATUS SRT_SOCKSTATUS -#define INIT SRTS_INIT -#define OPENED SRTS_OPENED -#define LISTENING SRTS_LISTENING -#define CONNECTING SRTS_CONNECTING -#define CONNECTED SRTS_CONNECTED -#define BROKEN SRTS_BROKEN -#define CLOSING SRTS_CLOSING -#define CLOSED SRTS_CLOSED -#define NONEXIST SRTS_NONEXIST -#endif - //////////////////////////////////////////////////////////////////////////////// struct CPerfMon @@ -236,166 +148,75 @@ typedef SRTSOCKET UDTSOCKET; //legacy alias #ifdef __cplusplus -// Class CUDTException exposed for C++ API. -// This is actually useless, unless you'd use a DIRECT C++ API, -// however there's no such API so far. The current C++ API for UDT/SRT -// is predicted to NEVER LET ANY EXCEPTION out of implementation, -// so it's useless to catch this exception anyway. - -class UDT_API CUDTException -{ -public: - - CUDTException(CodeMajor major = MJ_SUCCESS, CodeMinor minor = MN_NONE, int err = -1); - CUDTException(const CUDTException& e); - - ~CUDTException(); - - /// Get the description of the exception. - /// @return Text message for the exception description. - - const char* getErrorMessage(); - - /// Get the system errno for the exception. - /// @return errno. - - int getErrorCode() const; - - /// Get the system network errno for the exception. - /// @return errno. - - int getErrno() const; - /// Clear the error code. - - void clear(); - -private: - CodeMajor m_iMajor; // major exception categories - CodeMinor m_iMinor; // for specific error reasons - int m_iErrno; // errno returned by the system if there is any - std::string m_strMsg; // text error message - - std::string m_strAPI; // the name of UDT function that returns the error - std::string m_strDebug; // debug information, set to the original place that causes the error - -public: // Legacy Error Code - - static const int EUNKNOWN = SRT_EUNKNOWN; - static const int SUCCESS = SRT_SUCCESS; - static const int ECONNSETUP = SRT_ECONNSETUP; - static const int ENOSERVER = SRT_ENOSERVER; - static const int ECONNREJ = SRT_ECONNREJ; - static const int ESOCKFAIL = SRT_ESOCKFAIL; - static const int ESECFAIL = SRT_ESECFAIL; - static const int ECONNFAIL = SRT_ECONNFAIL; - static const int ECONNLOST = SRT_ECONNLOST; - static const int ENOCONN = SRT_ENOCONN; - static const int ERESOURCE = SRT_ERESOURCE; - static const int ETHREAD = SRT_ETHREAD; - static const int ENOBUF = SRT_ENOBUF; - static const int EFILE = SRT_EFILE; - static const int EINVRDOFF = SRT_EINVRDOFF; - static const int ERDPERM = SRT_ERDPERM; - static const int EINVWROFF = SRT_EINVWROFF; - static const int EWRPERM = SRT_EWRPERM; - static const int EINVOP = SRT_EINVOP; - static const int EBOUNDSOCK = SRT_EBOUNDSOCK; - static const int ECONNSOCK = SRT_ECONNSOCK; - static const int EINVPARAM = SRT_EINVPARAM; - static const int EINVSOCK = SRT_EINVSOCK; - static const int EUNBOUNDSOCK = SRT_EUNBOUNDSOCK; - static const int ESTREAMILL = SRT_EINVALMSGAPI; - static const int EDGRAMILL = SRT_EINVALBUFFERAPI; - static const int ENOLISTEN = SRT_ENOLISTEN; - static const int ERDVNOSERV = SRT_ERDVNOSERV; - static const int ERDVUNBOUND = SRT_ERDVUNBOUND; - static const int EINVALMSGAPI = SRT_EINVALMSGAPI; - static const int EINVALBUFFERAPI = SRT_EINVALBUFFERAPI; - static const int EDUPLISTEN = SRT_EDUPLISTEN; - static const int ELARGEMSG = SRT_ELARGEMSG; - static const int EINVPOLLID = SRT_EINVPOLLID; - static const int EASYNCFAIL = SRT_EASYNCFAIL; - static const int EASYNCSND = SRT_EASYNCSND; - static const int EASYNCRCV = SRT_EASYNCRCV; - static const int ETIMEOUT = SRT_ETIMEOUT; - static const int ECONGEST = SRT_ECONGEST; - static const int EPEERERR = SRT_EPEERERR; -}; +namespace srt { class CUDTException; } namespace UDT { -typedef CUDTException ERRORINFO; -//typedef UDT_SOCKOPT SOCKOPT; +typedef srt::CUDTException ERRORINFO; typedef CPerfMon TRACEINFO; -typedef CBytePerfMon TRACEBSTATS; -typedef ud_set UDSET; -UDT_API extern const SRTSOCKET INVALID_SOCK; +// This facility is used only for select() function. +// This is considered obsolete and the epoll() functionality rather should be used. +typedef std::set UDSET; +#define UD_CLR(u, uset) ((uset)->erase(u)) +#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) +#define UD_SET(u, uset) ((uset)->insert(u)) +#define UD_ZERO(uset) ((uset)->clear()) + +SRT_API extern const SRTSOCKET INVALID_SOCK; #undef ERROR -UDT_API extern const int ERROR; - -UDT_API int startup(); -UDT_API int cleanup(); -UDT_API UDTSOCKET socket(int af, int type, int protocol); -UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock); -UDT_API int listen(UDTSOCKET u, int backlog); -UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen); -UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int close(UDTSOCKET u); -UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); -UDT_API int setsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); -UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags); -UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags); - -UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, uint64_t srctime = 0); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len, uint64_t& srctime); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len); - -UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); -UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); +SRT_API extern const int ERROR; + +SRT_API int startup(); +SRT_API int cleanup(); +SRT_API SRTSOCKET socket(); +inline SRTSOCKET socket(int , int , int ) { return socket(); } +SRT_API int bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int bind2(SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int listen(SRTSOCKET u, int backlog); +SRT_API SRTSOCKET accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API int connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int close(SRTSOCKET u); +SRT_API int getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); +SRT_API int setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); +SRT_API int send(SRTSOCKET u, const char* buf, int len, int flags); +SRT_API int recv(SRTSOCKET u, char* buf, int len, int flags); + +SRT_API int sendmsg(SRTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, int64_t srctime = 0); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len, uint64_t& srctime); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len); + +SRT_API int64_t sendfile(SRTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile(SRTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); +SRT_API int64_t sendfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); // select and selectEX are DEPRECATED; please use epoll. -UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); -UDT_API int selectEx(const std::vector& fds, std::vector* readfds, - std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - -UDT_API int epoll_create(); -UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_remove_usock(int eid, UDTSOCKET u); -UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s); -UDT_API int epoll_update_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, +SRT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); +SRT_API int selectEx(const std::vector& fds, std::vector* readfds, + std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); + +SRT_API int epoll_create(); +SRT_API int epoll_add_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_remove_usock(int eid, SRTSOCKET u); +SRT_API int epoll_remove_ssock(int eid, SYSSOCKET s); +SRT_API int epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds = NULL, std::set* wrfds = NULL); -UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut, +SRT_API int epoll_wait2(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL); -UDT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); -UDT_API int epoll_release(int eid); -UDT_API ERRORINFO& getlasterror(); -UDT_API int getlasterror_code(); -UDT_API const char* getlasterror_desc(); -UDT_API int bstats(UDTSOCKET u, TRACEBSTATS* perf, bool clear = true); -UDT_API SRT_SOCKSTATUS getsockstate(UDTSOCKET u); - -// This is a C++ SRT API extension. This is not a part of legacy UDT API. -UDT_API void setloglevel(srt_logging::LogLevel::type ll); -UDT_API void addlogfa(srt_logging::LogFA fa); -UDT_API void dellogfa(srt_logging::LogFA fa); -UDT_API void resetlogfa(std::set fas); -UDT_API void resetlogfa(const int* fara, size_t fara_size); -UDT_API void setlogstream(std::ostream& stream); -UDT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); -UDT_API void setlogflags(int flags); - -UDT_API bool setstreamid(UDTSOCKET u, const std::string& sid); -UDT_API std::string getstreamid(UDTSOCKET u); +SRT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +SRT_API int epoll_release(int eid); +SRT_API ERRORINFO& getlasterror(); +SRT_API int getlasterror_code(); +SRT_API const char* getlasterror_desc(); +SRT_API int bstats(SRTSOCKET u, SRT_TRACEBSTATS* perf, bool clear = true); +SRT_API SRT_SOCKSTATUS getsockstate(SRTSOCKET u); } // namespace UDT @@ -405,7 +226,47 @@ UDT_API std::string getstreamid(UDTSOCKET u); // own logger FA objects, or create their own. The object of this type // is required to initialize the logger FA object. namespace srt_logging { struct LogConfig; } -UDT_API extern srt_logging::LogConfig srt_logger_config; +SRT_API extern srt_logging::LogConfig srt_logger_config; + +namespace srt +{ + +// This is a C++ SRT API extension. This is not a part of legacy UDT API. +SRT_API void setloglevel(srt_logging::LogLevel::type ll); +SRT_API void addlogfa(srt_logging::LogFA fa); +SRT_API void dellogfa(srt_logging::LogFA fa); +SRT_API void resetlogfa(std::set fas); +SRT_API void resetlogfa(const int* fara, size_t fara_size); +SRT_API void setlogstream(std::ostream& stream); +SRT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +SRT_API void setlogflags(int flags); + +SRT_API bool setstreamid(SRTSOCKET u, const std::string& sid); +SRT_API std::string getstreamid(SRTSOCKET u); + +// Namespace alias +namespace logging { + using namespace srt_logging; +} + +} // namespace srt + +// Planned deprecated removal: rel1.6.0 +// There's also no portable way possible to enforce a deprecation +// compiler warning, so leaving as is. +namespace UDT +{ + // Backward-compatible aliases, just for a case someone was using it. + using srt::setloglevel; + using srt::addlogfa; + using srt::dellogfa; + using srt::resetlogfa; + using srt::setlogstream; + using srt::setloghandler; + using srt::setlogflags; + using srt::setstreamid; + using srt::getstreamid; +} #endif /* __cplusplus */ diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/utilities.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/utilities.h new file mode 100644 index 000000000..31e05b205 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/utilities.h @@ -0,0 +1,1098 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_UTILITIES_H +#define INC_SRT_UTILITIES_H + +// Windows warning disabler +#define _CRT_SECURE_NO_WARNINGS 1 + +#include "platform_sys.h" +#include "srt_attr_defs.h" // defines HAVE_CXX11 + +// Happens that these are defined, undefine them in advance +#undef min +#undef max + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_CXX11 +#include +#endif + +#include +#include +#include +#include + +// -------------- UTILITIES ------------------------ + +// --- ENDIAN --- +// Copied from: https://gist.github.com/panzi/6856583 +// License: Public Domain. + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) + +# include + +// GLIBC-2.8 and earlier does not provide these macros. +// See http://linux.die.net/man/3/endian +// From https://gist.github.com/panzi/6856583 +# if defined(__GLIBC__) \ + && ( !defined(__GLIBC_MINOR__) \ + || ((__GLIBC__ < 2) \ + || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) ) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + +# define htole32(x) (x) +# define le32toh(x) (x) + +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) + +# define htole16(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) +# define le16toh(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) + +# define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) +# define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) + +# else +# error Byte Order not supported or not defined. +# endif +# endif + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + +# include + +#ifndef be16toh +# define be16toh(x) betoh16(x) +#endif +#ifndef le16toh +# define le16toh(x) letoh16(x) +#endif + +#ifndef be32toh +# define be32toh(x) betoh32(x) +#endif +#ifndef le32toh +# define le32toh(x) letoh32(x) +#endif + +#ifndef be64toh +# define be64toh(x) betoh64(x) +#endif +#ifndef le64toh +# define le64toh(x) letoh64(x) +#endif + +#elif defined(SUNOS) + + // SunOS/Solaris + + #include + #include + + #define __LITTLE_ENDIAN 1234 + #define __BIG_ENDIAN 4321 + + # if defined(_BIG_ENDIAN) + #define __BYTE_ORDER __BIG_ENDIAN + #define be64toh(x) (x) + #define be32toh(x) (x) + #define be16toh(x) (x) + #define le16toh(x) ((uint16_t)BSWAP_16(x)) + #define le32toh(x) BSWAP_32(x) + #define le64toh(x) BSWAP_64(x) + #define htobe16(x) (x) + #define htole16(x) ((uint16_t)BSWAP_16(x)) + #define htobe32(x) (x) + #define htole32(x) BSWAP_32(x) + #define htobe64(x) (x) + #define htole64(x) BSWAP_64(x) + # else + #define __BYTE_ORDER __LITTLE_ENDIAN + #define be64toh(x) BSWAP_64(x) + #define be32toh(x) ntohl(x) + #define be16toh(x) ntohs(x) + #define le16toh(x) (x) + #define le32toh(x) (x) + #define le64toh(x) (x) + #define htobe16(x) htons(x) + #define htole16(x) (x) + #define htobe32(x) htonl(x) + #define htole32(x) (x) + #define htobe64(x) BSWAP_64(x) + #define htole64(x) (x) + # endif + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error Endian: platform not supported + +#endif + +// Hardware <--> Network (big endian) convention +inline void HtoNLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htonl(src[i]); +} + +inline void NtoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = ntohl(src[i]); +} + +// Hardware <--> Intel (little endian) convention +inline void HtoILA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htole32(src[i]); +} + +inline void ItoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = le32toh(src[i]); +} + +// Bit numbering utility. +// +// This is something that allows you to turn 32-bit integers into bit fields. +// Although bitfields are part of C++ language, they are not designed to be +// interchanged with 32-bit numbers, and any attempt to doing it (by placing +// inside a union, for example) is nonportable (order of bitfields inside +// same-covering 32-bit integer number is dependent on the endian), so they are +// popularly disregarded as useless. Instead the 32-bit numbers with bits +// individually selected is preferred, with usually manual playing around with +// & and | operators, as well as << and >>. This tool is designed to simplify +// the use of them. This can be used to qualify a range of bits inside a 32-bit +// number to be a separate number, you can "wrap" it by placing the integer +// value in the range of these bits, as well as "unwrap" (extract) it from +// the given place. For your own safety, use one prefix to all constants that +// concern bit ranges intended to be inside the same "bit container". +// +// Usage: typedef Bits MASKTYPE; // MASKTYPE is a name of your choice. +// +// With this defined, you can use the following members: +// - MASKTYPE::mask - to get the int32_t value with bimask (used bits set to 1, others to 0) +// - MASKTYPE::offset - to get the lowermost bit number, or number of bits to shift +// - MASKTYPE::wrap(int value) - to create a bitset where given value is encoded in given bits +// - MASKTYPE::unwrap(int bitset) - to extract an integer value from the bitset basing on mask definition +// (rightmost defaults to leftmost) +// REMEMBER: leftmost > rightmost because bit 0 is the LEAST significant one! + +template +struct BitsetMask +{ + static const bool correct = L >= R; + static const uint32_t value = (1u << L) | BitsetMask::value; +}; + +// This is kind-of functional programming. This describes a special case that is +// a "terminal case" in case when decreased L-1 (see above) reached == R. +template +struct BitsetMask +{ + static const bool correct = true; + static const uint32_t value = 1u << R; +}; + +// This is a trap for a case that BitsetMask::correct in the master template definition +// evaluates to false. This trap causes compile error and prevents from continuing +// recursive unwinding in wrong direction (and challenging the compiler's resistiveness +// for infinite loops). +template +struct BitsetMask +{ +}; + +template +struct Bits +{ + // DID YOU GET a kind-of error: 'mask' is not a member of 'Bits<3u, 5u, false>'? + // See the the above declaration of 'correct'! + static const uint32_t mask = BitsetMask::value; + static const uint32_t offset = R; + static const size_t size = L - R + 1; + + // Example: if our bitset mask is 00111100, this checks if given value fits in + // 00001111 mask (that is, does not exceed <0, 15>. + static bool fit(uint32_t value) { return (BitsetMask::value & value) == value; } + + /// 'wrap' gets some given value that should be placed in appropriate bit range and + /// returns a whole 32-bit word that has the value already at specified place. + /// To create a 32-bit container that contains already all values destined for different + /// bit ranges, simply use wrap() for each of them and bind them with | operator. + static uint32_t wrap(uint32_t baseval) { return (baseval << offset) & mask; } + + /// Extracts appropriate bit range and returns them as normal integer value. + static uint32_t unwrap(uint32_t bitset) { return (bitset & mask) >> offset; } + + template + static T unwrapt(uint32_t bitset) { return static_cast(unwrap(bitset)); } +}; + + +//inline int32_t Bit(size_t b) { return 1 << b; } +// XXX This would work only with 'constexpr', but this is +// available only in C++11. In C++03 this can be only done +// using a macro. +// +// Actually this can be expressed in C++11 using a better technique, +// such as user-defined literals: +// 2_bit --> 1 >> 2 + +#ifdef BIT +#undef BIT +#endif +#define BIT(x) (1 << (x)) + + +// ------------------------------------------------------------ +// This is something that reminds a structure consisting of fields +// of the same type, implemented as an array. It's parametrized +// by the type of fields and the type, which's values should be +// used for indexing (preferably an enum type). Whatever type is +// used for indexing, it is converted to size_t for indexing the +// actual array. +// +// The user should use it as an array: ds[DS_NAME], stating +// that DS_NAME is of enum type passed as 3rd parameter. +// However trying to do ds[0] would cause a compile error. +template +struct DynamicStruct +{ + FieldType inarray[NoOfFields]; + + void clear() + { + // As a standard library, it can be believed that this call + // can be optimized when FieldType is some integer. + std::fill(inarray, inarray + NoOfFields, FieldType()); + } + + FieldType operator[](IndexerType ix) const { return inarray[size_t(ix)]; } + FieldType& operator[](IndexerType ix) { return inarray[size_t(ix)]; } + + template + FieldType operator[](AnyOther ix) const + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + template + FieldType& operator[](AnyOther ix) + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + operator FieldType* () { return inarray; } + operator const FieldType* () const { return inarray; } + + char* raw() { return (char*)inarray; } +}; + + +/// Fixed-size array template class. +namespace srt { + +template +class FixedArray +{ +public: + FixedArray(size_t size) + : m_size(size) + , m_entries(new T[size]) + { + } + + ~FixedArray() + { + delete [] m_entries; + } + +public: + const T& operator[](size_t index) const + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](size_t index) + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + const T& operator[](int index) const + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](int index) + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + size_t size() const { return m_size; } + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin() { return m_entries; } + iterator end() { return m_entries + m_size; } + + const_iterator cbegin() const { return m_entries; } + const_iterator cend() const { return m_entries + m_size; } + + T* data() { return m_entries; } + +private: + FixedArray(const FixedArray& ); + FixedArray& operator=(const FixedArray&); + + void raise_expection(int i) const + { + std::stringstream ss; + ss << "Index " << i << "out of range"; + throw std::runtime_error(ss.str()); + } + +private: + size_t m_size; + T* const m_entries; +}; + +} // namespace srt + +// ------------------------------------------------------------ + + + +inline bool IsSet(int32_t bitset, int32_t flagset) +{ + return (bitset & flagset) == flagset; +} + +// std::addressof in C++11, +// needs to be provided for C++03 +template +inline RefType* AddressOf(RefType& r) +{ + return (RefType*)(&(unsigned char&)(r)); +} + +template +struct explicit_t +{ + T inobject; + explicit_t(const T& uo): inobject(uo) {} + + operator T() const { return inobject; } + +private: + template + explicit_t(const X& another); +}; + +// This is required for Printable function if you have a container of pairs, +// but this function has a different definition for C++11 and C++03. +namespace srt_pair_op +{ + template + std::ostream& operator<<(std::ostream& s, const std::pair& v) + { + s << "{" << v.first << " " << v.second << "}"; + return s; + } +} + +#if HAVE_CXX11 + +template +inline auto Move(In& i) -> decltype(std::move(i)) { return std::move(i); } + +// Gluing string of any type, wrapper for operator << + +template +inline Stream& Print(Stream& in) { return in;} + +template +inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args) +{ + sout << arg1; + return Print(sout, args...); +} + +template +inline std::string Sprint(Args&&... args) +{ + std::ostringstream sout; + Print(sout, args...); + return sout.str(); +} + +// We need to use UniquePtr, in the form of C++03 it will be a #define. +// Naturally will be used std::move() so that it can later painlessly +// switch to C++11. +template +using UniquePtr = std::unique_ptr; + +template inline +std::string Printable(const Container& in, Value /*pseudoargument*/, Args&&... args) +{ + using namespace srt_pair_op; + std::ostringstream os; + Print(os, args...); + os << "[ "; + for (auto i: in) + os << Value(i) << " "; + os << "]"; + return os.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + using Value = typename Container::value_type; + return Printable(in, Value()); +} + +template +auto map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) -> typename Map::mapped_type +{ + auto it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +auto map_getp(Map& m, const Key& key) -> typename Map::mapped_type* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + +template +auto map_getp(const Map& m, const Key& key) -> typename Map::mapped_type const* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + + +#else + +// The unique_ptr requires C++11, and the rvalue-reference feature, +// so here we're simulate the behavior using the old std::auto_ptr. + +// This is only to make a "move" call transparent and look ok towards +// the C++11 code. +template +std::auto_ptr_ref Move(const std::auto_ptr_ref& in) { return in; } + +// We need to provide also some fixes for this type that were not present in auto_ptr, +// but they are present in unique_ptr. + +// C++03 doesn't have a templated typedef, but still we need some things +// that can only function as a class. +template +class UniquePtr: public std::auto_ptr +{ + typedef std::auto_ptr Base; + +public: + + // This is a template - so method names must be declared explicitly + typedef typename Base::element_type element_type; + using Base::get; + using Base::reset; + + // All constructor declarations must be repeated. + // "Constructor delegation" is also only C++11 feature. + explicit UniquePtr(element_type* p = 0) throw() : Base(p) {} + UniquePtr(UniquePtr& a) throw() : Base(a) { } + template + UniquePtr(UniquePtr& a) throw() : Base(a) {} + + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + template + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + + // Good, now we need to add some parts of the API of unique_ptr. + + bool operator==(const UniquePtr& two) const { return get() == two.get(); } + bool operator!=(const UniquePtr& two) const { return get() != two.get(); } + + bool operator==(const element_type* two) const { return get() == two; } + bool operator!=(const element_type* two) const { return get() != two; } + + operator bool () { return 0!= get(); } +}; + +// A primitive one-argument versions of Sprint and Printable +template +inline std::string Sprint(const Arg1& arg) +{ + std::ostringstream sout; + sout << arg; + return sout.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator i = in.begin(); i != in.end(); ++i) + os << Value(*i) << " "; + os << "]"; + + return os.str(); +} + +template +typename Map::mapped_type map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type map_get(const Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type* map_getp(Map& m, const Key& key) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +template +typename Map::mapped_type const* map_getp(const Map& m, const Key& key) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +#endif + +// Printable with prefix added for every element. +// Useful when printing a container of sockets or sequence numbers. +template inline +std::string PrintableMod(const Container& in, const std::string& prefix) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator y = in.begin(); y != in.end(); ++y) + os << prefix << Value(*y) << " "; + os << "]"; + return os.str(); +} + +template +inline void FilterIf(InputIterator bg, InputIterator nd, + OutputIterator out, TransFunction fn) +{ + for (InputIterator i = bg; i != nd; ++i) + { + std::pair result = fn(*i); + if (!result.second) + continue; + *out++ = result.first; + } +} + +template +inline void insert_uniq(std::vector& v, const ArgValue& val) +{ + typename std::vector::iterator i = std::find(v.begin(), v.end(), val); + if (i != v.end()) + return; + + v.push_back(val); +} + +template +struct CallbackHolder +{ + void* opaque; + Signature* fn; + + CallbackHolder(): opaque(NULL), fn(NULL) {} + + void set(void* o, Signature* f) + { + // Test if the pointer is a pointer to function. Don't let + // other type of pointers here. +#if HAVE_CXX11 + static_assert(std::is_function::value, "CallbackHolder is for functions only!"); +#else + // This is a poor-man's replacement, which should in most compilers + // generate a warning, if `Signature` resolves to a value type. + // This would make an illegal pointer cast from a value to a function type. + // Casting function-to-function, however, should not. Unfortunately + // newer compilers disallow that, too (when a signature differs), but + // then they should better use the C++11 way, much more reliable and safer. + void* (*testfn)(void*) = (void*(*)(void*))f; + (void)(testfn); +#endif + opaque = o; + fn = f; + } + + operator bool() { return fn != NULL; } +}; + +#define CALLBACK_CALL(holder,...) (*holder.fn)(holder.opaque, __VA_ARGS__) + +inline std::string FormatBinaryString(const uint8_t* bytes, size_t size) +{ + if ( size == 0 ) + return ""; + + //char buf[256]; + using namespace std; + + ostringstream os; + + // I know, it's funny to use sprintf and ostringstream simultaneously, + // but " %02X" in iostream is: << " " << hex << uppercase << setw(2) << setfill('0') << VALUE << setw(1) + // Too noisy. OTOH ostringstream solves the problem of memory allocation + // for a string of unpredictable size. + //sprintf(buf, "%02X", int(bytes[0])); + + os.fill('0'); + os.width(2); + os.setf(ios::basefield, ios::hex); + os.setf(ios::uppercase); + + //os << buf; + os << int(bytes[0]); + + + for (size_t i = 1; i < size; ++i) + { + //sprintf(buf, " %02X", int(bytes[i])); + //os << buf; + os << int(bytes[i]); + } + return os.str(); +} + + +/// This class is useful in every place where +/// the time drift should be traced. It's currently in use in every +/// solution that implements any kind of TSBPD. +template +class DriftTracer +{ + int64_t m_qDrift; + int64_t m_qOverdrift; + + int64_t m_qDriftSum; + unsigned m_uDriftSpan; + +public: + DriftTracer() + : m_qDrift(0) + , m_qOverdrift(0) + , m_qDriftSum(0) + , m_uDriftSpan(0) + {} + + bool update(int64_t driftval) + { + m_qDriftSum += driftval; + ++m_uDriftSpan; + + // I moved it here to calculate accumulated overdrift. + if (CLEAR_ON_UPDATE) + m_qOverdrift = 0; + + if (m_uDriftSpan < MAX_SPAN) + return false; + + + // Calculate the median of all drift values. + // In most cases, the divisor should be == MAX_SPAN. + m_qDrift = m_qDriftSum / m_uDriftSpan; + + // And clear the collection + m_qDriftSum = 0; + m_uDriftSpan = 0; + + // In case of "overdrift", save the overdriven value in 'm_qOverdrift'. + // In clear mode, you should add this value to the time base when update() + // returns true. The drift value will be since now measured with the + // overdrift assumed to be added to the base. + if (std::abs(m_qDrift) > MAX_DRIFT) + { + m_qOverdrift = m_qDrift < 0 ? -MAX_DRIFT : MAX_DRIFT; + m_qDrift -= m_qOverdrift; + } + + // printDriftOffset(m_qOverdrift, m_qDrift); + + // Timebase is separate + // m_qTimeBase += m_qOverdrift; + + return true; + } + + // For group overrides + void forceDrift(int64_t driftval) + { + m_qDrift = driftval; + } + + // These values can be read at any time, however if you want + // to depend on the fact that they have been changed lately, + // you have to check the return value from update(). + // + // IMPORTANT: drift() can be called at any time, just remember + // that this value may look different than before only if the + // last update() returned true, which need not be important for you. + // + // CASE: CLEAR_ON_UPDATE = true + // overdrift() should be read only immediately after update() returned + // true. It will stay available with this value until the next time when + // update() returns true, in which case the value will be cleared. + // Therefore, after calling update() if it retuns true, you should read + // overdrift() immediately an make some use of it. Next valid overdrift + // will be then relative to every previous overdrift. + // + // CASE: CLEAR_ON_UPDATE = false + // overdrift() will start from 0, but it will always keep track on + // any changes in overdrift. By manipulating the MAX_DRIFT parameter + // you can decide how high the drift can go relatively to stay below + // overdrift. + int64_t drift() const { return m_qDrift; } + int64_t overdrift() const { return m_qOverdrift; } +}; + +template +struct MapProxy +{ + std::map& mp; + const KeyType& key; + + MapProxy(std::map& m, const KeyType& k): mp(m), key(k) {} + + void operator=(const ValueType& val) + { + mp[key] = val; + } + + typename std::map::iterator find() + { + return mp.find(key); + } + + typename std::map::const_iterator find() const + { + return mp.find(key); + } + + operator ValueType() const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return ""; + return p->second; + } + + ValueType deflt(const ValueType& defval) const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return defval; + return p->second; + } + + bool exists() const + { + return find() != mp.end(); + } +}; + +/// Print some hash-based stamp of the first 16 bytes in the buffer +inline std::string BufferStamp(const char* mem, size_t size) +{ + using namespace std; + char spread[16]; + + if (size < 16) + memset((spread + size), 0, 16 - size); + memcpy((spread), mem, min(size_t(16), size)); + + // Now prepare 4 cells for uint32_t. + union + { + uint32_t sum; + char cells[4]; + }; + memset((cells), 0, 4); + + for (size_t x = 0; x < 4; ++x) + for (size_t y = 0; y < 4; ++y) + { + cells[x] += spread[x+4*y]; + } + + // Convert to hex string + ostringstream os; + os << hex << uppercase << setfill('0') << setw(8) << sum; + + return os.str(); +} + +template +inline void Split(const std::string & str, char delimiter, OutputIterator tokens) +{ + if ( str.empty() ) + return; // May cause crash and won't extract anything anyway + + std::size_t start; + std::size_t end = -1; + + do + { + start = end + 1; + end = str.find(delimiter, start); + *tokens = str.substr( + start, + (end == std::string::npos) ? std::string::npos : end - start); + ++tokens; + } while (end != std::string::npos); +} + +inline std::string SelectNot(const std::string& unwanted, const std::string& s1, const std::string& s2) +{ + if (s1 == unwanted) + return s2; // might be unwanted, too, but then, there's nothing you can do anyway + if (s2 == unwanted) + return s1; + + // Both have wanted values, so now compare if they are same + if (s1 == s2) + return s1; // occasionally there's a winner + + // Irresolvable situation. + return std::string(); +} + +inline std::string SelectDefault(const std::string& checked, const std::string& def) +{ + if (checked == "") + return def; + return checked; +} + +template +inline size_t safe_advance(It& it, size_t num, It end) +{ + while ( it != end && num ) + { + --num; + ++it; + } + + return num; // will be effectively 0, if reached the required point, or >0, if end was by that number earlier +} + +// This is available only in C++17, dunno why not C++11 as it's pretty useful. +template inline +ATR_CONSTEXPR size_t Size(const V (&)[N]) ATR_NOEXCEPT { return N; } + +template +inline ValueType avg_iir(ValueType old_value, ValueType new_value) +{ + return (old_value * (DEPRLEN - 1) + new_value) / DEPRLEN; +} + +template +inline ValueType avg_iir_w(ValueType old_value, ValueType new_value, size_t new_val_weight) +{ + return (old_value * (DEPRLEN - new_val_weight) + new_value * new_val_weight) / DEPRLEN; +} + +// Property accessor definitions +// +// "Property" is a special method that accesses given field. +// This relies only on a convention, which is the following: +// +// V x = object.prop(); <-- get the property's value +// object.prop(x); <-- set the property a value +// +// Properties might be also chained when setting: +// +// object.prop1(v1).prop2(v2).prop3(v3); +// +// Properties may be defined various even very complicated +// ways, which is simply providing a method with body. In order +// to define a property simplest possible way, that is, refer +// directly to the field that keeps it, here are the following macros: +// +// Prefix: SRTU_PROPERTY_ +// Followed by: +// - access type: RO, WO, RW, RR, RRW +// - chain flag: optional _CHAIN +// Where access type is: +// - RO - read only. Defines reader accessor. The accessor method will be const. +// - RR - read reference. The accessor isn't const to allow reference passthrough. +// - WO - write only. Defines writer accessor. +// - RW - combines RO and WO. +// - RRW - combines RR and WO. +// +// The _CHAIN marker is optional for macros providing writable accessors +// for properties. The difference is that while simple write accessors return +// void, the chaining accessors return the reference to the object for which +// the write accessor was called so that you can call the next accessor (or +// any other method as well) for the result. + +#define SRTU_PROPERTY_RR(type, name, field) type name() { return field; } +#define SRTU_PROPERTY_RO(type, name, field) type name() const { return field; } +#define SRTU_PROPERTY_WO(type, name, field) void set_##name(type arg) { field = arg; } +#define SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) otype& set_##name(type arg) { field = arg; return *this; } +#define SRTU_PROPERTY_RW(type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RRW(type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) +#define SRTU_PROPERTY_RRW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/version.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/version.h index 7033968e8..b2773dd3b 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/version.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/version.h @@ -23,10 +23,10 @@ written by #define SRT_VERSION_MAJOR 1 #define SRT_VERSION_MINOR 5 -#define SRT_VERSION_PATCH 1 +#define SRT_VERSION_PATCH 3 /* #undef SRT_VERSION_BUILD */ -#define SRT_VERSION_STRING "1.5.1" +#define SRT_VERSION_STRING "1.5.3" #define SRT_VERSION_VALUE \ SRT_MAKE_VERSION_VALUE( \ SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH ) diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/window.h b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/window.h new file mode 100644 index 000000000..ecc4a4947 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64/Headers/window.h @@ -0,0 +1,355 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/22/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_WINDOW_H +#define INC_SRT_WINDOW_H + + +#ifndef _WIN32 + #include + #include +#endif +#include "packet.h" +#include "udt.h" + +namespace srt +{ + +namespace ACKWindowTools +{ + struct Seq + { + int32_t iACKSeqNo; // Seq. No. of the ACK packet + int32_t iACK; // Data packet Seq. No. carried by the ACK packet + sync::steady_clock::time_point tsTimeStamp; // The timestamp when the ACK was sent + }; + + void store(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t ack); + int acknowledge(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime); +} + +template +class CACKWindow +{ +public: + CACKWindow() : + m_aSeq(), + m_iHead(0), + m_iTail(0) + { + m_aSeq[0].iACKSeqNo = SRT_SEQNO_NONE; + } + + ~CACKWindow() {} + + /// Write an ACK record into the window. + /// @param [in] seq Seq. No. of the ACK packet + /// @param [in] ack Data packet Seq. No. carried by the ACK packet + + void store(int32_t seq, int32_t ack) + { + return ACKWindowTools::store(m_aSeq, SIZE, m_iHead, m_iTail, seq, ack); + } + + /// Search the ACKACK "seq" in the window, find out the data packet "ack" + /// and calculate RTT estimate based on the ACK/ACKACK pair + /// @param [in] seq Seq. No. of the ACK packet carried within ACKACK + /// @param [out] ack Acknowledged data packet Seq. No. from the ACK packet that matches the ACKACK + /// @param [in] currtime The timestamp of ACKACK packet reception by the receiver + /// @return RTT + + int acknowledge(int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime) + { + return ACKWindowTools::acknowledge(m_aSeq, SIZE, m_iHead, m_iTail, seq, r_ack, currtime); + } + +private: + + typedef ACKWindowTools::Seq Seq; + + Seq m_aSeq[SIZE]; + int m_iHead; // Pointer to the latest ACK record + int m_iTail; // Pointer to the oldest ACK record + +private: + CACKWindow(const CACKWindow&); + CACKWindow& operator=(const CACKWindow&); +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CPktTimeWindowTools +{ +public: + static int getPktRcvSpeed_in(const int* window, int* replica, const int* bytes, size_t asize, int& bytesps); + static int getBandwidth_in(const int* window, int* replica, size_t psize); + + static void initializeWindowArrays(int* r_pktWindow, int* r_probeWindow, int* r_bytesWindow, size_t asize, size_t psize); +}; + +template +class CPktTimeWindow: CPktTimeWindowTools +{ +public: + CPktTimeWindow(): + m_aPktWindow(), + m_aBytesWindow(), + m_iPktWindowPtr(0), + m_aProbeWindow(), + m_iProbeWindowPtr(0), + m_iLastSentTime(0), + m_iMinPktSndInt(1000000), + m_tsLastArrTime(sync::steady_clock::now()), + m_tsCurrArrTime(), + m_tsProbeTime(), + m_Probe1Sequence(SRT_SEQNO_NONE) + { + // Exception: up to CUDT ctor + sync::setupMutex(m_lockPktWindow, "PktWindow"); + sync::setupMutex(m_lockProbeWindow, "ProbeWindow"); + CPktTimeWindowTools::initializeWindowArrays(m_aPktWindow, m_aProbeWindow, m_aBytesWindow, ASIZE, PSIZE); + } + + ~CPktTimeWindow() + { + } + +public: + /// read the minimum packet sending interval. + /// @return minimum packet sending interval (microseconds). + + int getMinPktSndInt() const { return m_iMinPktSndInt; } + + /// Calculate the packets arrival speed. + /// @return Packet arrival speed (packets per second). + + int getPktRcvSpeed(int& w_bytesps) const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockPktWindow); + + int pktReplica[ASIZE]; // packet information window (inter-packet time) + return getPktRcvSpeed_in(m_aPktWindow, pktReplica, m_aBytesWindow, ASIZE, (w_bytesps)); + } + + int getPktRcvSpeed() const + { + int bytesps; + return getPktRcvSpeed((bytesps)); + } + + /// Estimate the bandwidth. + /// @return Estimated bandwidth (packets per second). + + int getBandwidth() const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + int probeReplica[PSIZE]; + return getBandwidth_in(m_aProbeWindow, probeReplica, PSIZE); + } + + /// Record time information of a packet sending. + /// @param currtime timestamp of the packet sending. + + void onPktSent(int currtime) + { + int interval = currtime - m_iLastSentTime; + + if ((interval < m_iMinPktSndInt) && (interval > 0)) + m_iMinPktSndInt = interval; + + m_iLastSentTime = currtime; + } + + /// Record time information of an arrived packet. + + void onPktArrival(int pktsz = 0) + { + sync::ScopedLock cg(m_lockPktWindow); + + m_tsCurrArrTime = sync::steady_clock::now(); + + // record the packet interval between the current and the last one + m_aPktWindow[m_iPktWindowPtr] = (int) sync::count_microseconds(m_tsCurrArrTime - m_tsLastArrTime); + m_aBytesWindow[m_iPktWindowPtr] = pktsz; + + // the window is logically circular + ++ m_iPktWindowPtr; + if (m_iPktWindowPtr == ASIZE) + m_iPktWindowPtr = 0; + + // remember last packet arrival time + m_tsLastArrTime = m_tsCurrArrTime; + } + + /// Shortcut to test a packet for possible probe 1 or 2 + void probeArrival(const CPacket& pkt, bool unordered) + { + const int inorder16 = pkt.m_iSeqNo & PUMASK_SEQNO_PROBE; + + // for probe1, we want 16th packet + if (inorder16 == 0) + { + probe1Arrival(pkt, unordered); + } + + if (unordered) + return; + + // for probe2, we want 17th packet + if (inorder16 == 1) + { + probe2Arrival(pkt); + } + } + + /// Record the arrival time of the first probing packet. + void probe1Arrival(const CPacket& pkt, bool unordered) + { + if (unordered && pkt.m_iSeqNo == m_Probe1Sequence) + { + // Reset the starting probe into "undefined", when + // a packet has come as retransmitted before the + // measurement at arrival of 17th could be taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + return; + } + + m_tsProbeTime = sync::steady_clock::now(); + m_Probe1Sequence = pkt.m_iSeqNo; // Record the sequence where 16th packet probe was taken + } + + /// Record the arrival time of the second probing packet and the interval between packet pairs. + + void probe2Arrival(const CPacket& pkt) + { + // Reject probes that don't refer to the very next packet + // towards the one that was lately notified by probe1Arrival. + // Otherwise the result can be stupid. + + // Simply, in case when this wasn't called exactly for the + // expected packet pair, behave as if the 17th packet was lost. + + // no start point yet (or was reset) OR not very next packet + if (m_Probe1Sequence == SRT_SEQNO_NONE || CSeqNo::incseq(m_Probe1Sequence) != pkt.m_iSeqNo) + return; + + // Grab the current time before trying to acquire + // a mutex. This might add extra delay and therefore + // screw up the measurement. + const sync::steady_clock::time_point now = sync::steady_clock::now(); + + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + m_tsCurrArrTime = now; + + // Reset the starting probe to prevent checking if the + // measurement was already taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + + // record the probing packets interval + // Adjust the time for what a complete packet would have take + const int64_t timediff = sync::count_microseconds(m_tsCurrArrTime - m_tsProbeTime); + const int64_t timediff_times_pl_size = timediff * CPacket::SRT_MAX_PAYLOAD_SIZE; + + // Let's take it simpler than it is coded here: + // (stating that a packet has never zero size) + // + // probe_case = (now - previous_packet_time) * SRT_MAX_PAYLOAD_SIZE / pktsz; + // + // Meaning: if the packet is fully packed, probe_case = timediff. + // Otherwise the timediff will be "converted" to a time that a fully packed packet "would take", + // provided the arrival time is proportional to the payload size and skipping + // the ETH+IP+UDP+SRT header part elliminates the constant packet delivery time influence. + // + const size_t pktsz = pkt.getLength(); + m_aProbeWindow[m_iProbeWindowPtr] = pktsz ? int(timediff_times_pl_size / pktsz) : int(timediff); + + // OLD CODE BEFORE BSTATS: + // record the probing packets interval + // m_aProbeWindow[m_iProbeWindowPtr] = int(m_tsCurrArrTime - m_tsProbeTime); + + // the window is logically circular + ++ m_iProbeWindowPtr; + if (m_iProbeWindowPtr == PSIZE) + m_iProbeWindowPtr = 0; + } + +private: + int m_aPktWindow[ASIZE]; // Packet information window (inter-packet time) + int m_aBytesWindow[ASIZE]; + int m_iPktWindowPtr; // Position pointer of the packet info. window + mutable sync::Mutex m_lockPktWindow; // Used to synchronize access to the packet window + + int m_aProbeWindow[PSIZE]; // Record inter-packet time for probing packet pairs + int m_iProbeWindowPtr; // Position pointer to the probing window + mutable sync::Mutex m_lockProbeWindow; // Used to synchronize access to the probe window + + int m_iLastSentTime; // Last packet sending time + int m_iMinPktSndInt; // Minimum packet sending interval + + sync::steady_clock::time_point m_tsLastArrTime; // Last packet arrival time + sync::steady_clock::time_point m_tsCurrArrTime; // Current packet arrival time + sync::steady_clock::time_point m_tsProbeTime; // Arrival time of the first probing packet + int32_t m_Probe1Sequence; // Sequence number for which the arrival time was notified + +private: + CPktTimeWindow(const CPktTimeWindow&); + CPktTimeWindow &operator=(const CPktTimeWindow&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64/libsrt.a b/Vendor/SRT/libsrt.xcframework/ios-arm64/libsrt.a index 41022b64d4aa692790973a28300a13c305786238..ec6920aa2bc89ee4a5733673b6359d9d27f75dd2 100644 GIT binary patch delta 876 zcmXBROGs2v7{GBH$0^4wM@Kt%YJ6o@_8N6;yrrf+%xo;3p4!7wdzhL{`N&r_>M+pC zp=>DHSc$lBQ4j}$0&!tN3nxejMoHQz6yc&pi=e;P#c%QdzI!j{a2H+;>K8Cz)jMpq z%s|R>tMI5^HO#B(ylS{t)qB;5cdDV)74FE&4U9ic6}~B#0juPcYxTbgZ5&Kb6M@Lt zyeRoIA@WO;HuHyag#6YY`Dbz^gGM12oyMM6Ej=0OitMd6>Lauq|D*~zRA>CvsB>fm zzK1M|91R++!&((5D!%!)D6By=*2?*|brD~ex6?C;iVSncdHyB^Eg`Y3_4t=?@weS);~3d99_VyGr;>bMewNmr!QXMn%(Hqw{w{s7uTF zkVQy$!}@QGo3*US+ z!sl*LV8I4#gcXTMLNZd2icLtvW~5^awqhGHupK+F6T7e*He@0T*{~xAd*DDWRP4n* zQ~(IEPA9;XE$jA}*mC zmvIF(s6`#F;u@~w2I_GW4QNCYZlM{s;l>@@MGIQdhIZUT2RhM(ZuHfhY$|WDYI~@j$qkU?TA#M8l;CL`*Oy99%wM55Hu-|IB2P2|j(O3F1M5#_4oq zC?lOZOS|ls!~Al%Uykt08owO*O4j<^5l%;%QvM@R3XHk6SR}^Wi+{fljT?=UqMOW) z60>IA$69qZ}Vu0*ig^vjhiIGv0-=pULPZDLBaXrt}9RHgv1q@Sh!Z2knGN_}Ww|TrVXa3Txq}-QmqQ2Vl zr#G~`8!efi@FmJuZHZmH9*~T6p*MbJ*~E-w?an71ip!a56^|>dZ(`K!9gw7e$7_WR zcElqA%drB9ScxR8!fGTV1#7St>#!ahkcy4igw5E3G^E3U3~YrH+aMzo+mVHA8I<5G&Y=`#D93qJ zpb{5w5tncoRk(s`)SwnuQHOeXa1Gbt#SQq-fSYJU6PnS2R@}mEw4ogxxFbB?&W6c< Dwl`c6 diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/access_control.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/access_control.h index 97a1104a8..611e1dad8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/access_control.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/access_control.h @@ -41,7 +41,7 @@ written by // CODE NOT IN USE 408: unused: no timeout predicted for listener callback #define SRT_REJX_CONFLICT 1409 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only. // CODE NOT IN USE 410: unused: treated as a specific case of 404 -// CODE NOT IN USE 411: unused: no reason to include lenght in the protocol +// CODE NOT IN USE 411: unused: no reason to include length in the protocol // CODE NOT IN USE 412: unused: preconditions not predicted in AC // CODE NOT IN USE 413: unused: AC size is already defined as 512 // CODE NOT IN USE 414: unused: AC size is already defined as 512 diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/api.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/api.h index ca812bf9e..9ba77d23a 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/api.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/api.h @@ -193,6 +193,15 @@ class CUDTSocket /// to finish sending the data that were scheduled for sending so far. void setClosed(); + // This is necessary to be called from the group before the group clears + // the connection with the socket. As for managed groups (and there are + // currently no other group types), a socket disconnected from the group + // is no longer usable. + void setClosing() + { + core().m_bClosing = true; + } + /// This does the same as setClosed, plus sets the m_bBroken to true. /// Such a socket can still be read from so that remaining data from /// the receiver buffer can be read, but no longer sends anything. @@ -447,6 +456,8 @@ class CUDTUnited /// @param cfgSocket socket configuration. /// @return tru if configurations match, false otherwise. static bool channelSettingsMatch(const CSrtMuxerConfig& cfgMuxer, const CSrtConfig& cfgSocket); + static bool inet6SettingsCompat(const sockaddr_any& muxaddr, const CSrtMuxerConfig& cfgMuxer, + const sockaddr_any& reqaddr, const CSrtMuxerConfig& cfgSocket); private: std::map m_mMultiplexer; // UDP multiplexer diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer.h deleted file mode 100644 index 48bcb4311..000000000 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer.h +++ /dev/null @@ -1,611 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2009 -modified by - Haivision Systems Inc. -*****************************************************************************/ - -#ifndef INC_SRT_BUFFER_H -#define INC_SRT_BUFFER_H - -#include "udt.h" -#include "list.h" -#include "queue.h" -#include "tsbpd_time.h" -#include "utilities.h" - -// The notation used for "circular numbers" in comments: -// The "cicrular numbers" are numbers that when increased up to the -// maximum become zero, and similarly, when the zero value is decreased, -// it turns into the maximum value minus one. This wrapping works the -// same for adding and subtracting. Circular numbers cannot be multiplied. - -// Operations done on these numbers are marked with additional % character: -// a %> b : a is later than b -// a ++% (++%a) : shift a by 1 forward -// a +% b : shift a by b -// a == b : equality is same as for just numbers - -namespace srt { - -/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) -class AvgBufSize -{ - typedef sync::steady_clock::time_point time_point; - -public: - AvgBufSize() - : m_dBytesCountMAvg(0.0) - , m_dCountMAvg(0.0) - , m_dTimespanMAvg(0.0) - { - } - -public: - bool isTimeToUpdate(const time_point& now) const; - void update(const time_point& now, int pkts, int bytes, int timespan_ms); - -public: - inline double pkts() const { return m_dCountMAvg; } - inline double timespan_ms() const { return m_dTimespanMAvg; } - inline double bytes() const { return m_dBytesCountMAvg; } - -private: - time_point m_tsLastSamplingTime; - double m_dBytesCountMAvg; - double m_dCountMAvg; - double m_dTimespanMAvg; -}; - -/// The class to estimate source bitrate based on samples submitted to the buffer. -/// Is currently only used by the CSndBuffer. -class CRateEstimator -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; -public: - CRateEstimator(); - -public: - uint64_t getInRatePeriod() const { return m_InRatePeriod; } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_iInRateBps; } - - void setInputRateSmpPeriod(int period); - - /// Update input rate calculation. - /// @param [in] time current time in microseconds - /// @param [in] pkts number of packets newly added to the buffer - /// @param [in] bytes number of payload bytes in those newly added packets - /// - /// @return Current size of the data in the sending list. - void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); - - void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } - -private: // Constants - static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms - static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms - static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload - static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; - -private: - int m_iInRatePktsCount; // number of payload bytes added since InRateStartTime - int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime - time_point m_tsInRateStartTime; - uint64_t m_InRatePeriod; // usec - int m_iInRateBps; // Input Rate in Bytes/sec -}; - -class CSndBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the buffer is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - /// @brief CSndBuffer constructor. - /// @param size initial number of blocks (each block to store one packet payload). - /// @param maxpld maximum packet payload. - CSndBuffer(int size = 32, int maxpld = 1500); - ~CSndBuffer(); - -public: - /// Insert a user buffer into the sending list. - /// For @a w_mctrl the following fields are used: - /// INPUT: - /// - msgttl: timeout for retransmitting the message, if lost - /// - inorder: request to deliver the message in order of sending - /// - srctime: local time as a base for packet's timestamp (0 if unused) - /// - pktseq: sequence number to be stamped on the packet (-1 if unused) - /// - msgno: message number to be stamped on the packet (-1 if unused) - /// OUTPUT: - /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) - /// - pktseq: sequence number to be stamped on the next packet - /// - msgno: message number stamped on the packet - /// @param [in] data pointer to the user data block. - /// @param [in] len size of the block. - /// @param [inout] w_mctrl Message control data - SRT_ATTR_EXCLUDES(m_BufLock) - void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); - - /// Read a block of data from file and insert it into the sending list. - /// @param [in] ifs input file stream. - /// @param [in] len size of the block. - /// @return actual size of data added from the file. - SRT_ATTR_EXCLUDES(m_BufLock) - int addBufferFromFile(std::fstream& ifs, int len); - - /// Find data position to pack a DATA packet from the furthest reading point. - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [in] kflags Odd|Even crypto key flag - /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. - /// @return Actual length of data read. - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); - - /// Peek an information on the next original data packet to send. - /// @return origin time stamp of the next packet; epoch start time otherwise. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point peekNextOriginal() const; - - /// Find data position to pack a DATA packet for a retransmission. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [out] msglen length of the message - /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); - - /// Get the time of the last retransmission (if any) of the DATA packet. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// - /// @return Last time of the last retransmission event for the corresponding DATA packet. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point getPacketRexmitTime(const int offset); - - /// Update the ACK point and may release/unmap/return the user data according to the flag. - /// @param [in] offset number of packets acknowledged. - int32_t getMsgNoAt(const int offset); - - void ackData(int offset); - - /// Read size of data still in the sending list. - /// @return Current size of the data in the sending list. - int getCurrBufSize() const; - - SRT_ATTR_EXCLUDES(m_BufLock) - int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); - - void updAvgBufSize(const time_point& time); - int getAvgBufSize(int& bytes, int& timespan); - int getCurrBufSize(int& bytes, int& timespan); - - /// @brief Get the buffering delay of the oldest message in the buffer. - /// @return the delay value. - SRT_ATTR_EXCLUDES(m_BufLock) - duration getBufferingDelay(const time_point& tnow) const; - - uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_rateEstimator.getInputRate(); } - - void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } - - const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } - - void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } - -private: - void increase(); - -private: - mutable sync::Mutex m_BufLock; // used to synchronize buffer operation - - struct Block - { - char* m_pcData; // pointer to the data block - int m_iLength; // payload length of the block. - - int32_t m_iMsgNoBitset; // message number - int32_t m_iSeqNo; // sequence number for scheduling - time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. - time_point m_tsRexmitTime; // packet retransmission time - int m_iTTL; // time to live (milliseconds) - - Block* m_pNext; // next block - - int32_t getMsgSeq() - { - // NOTE: this extracts message ID with regard to REXMIT flag. - // This is valid only for message ID that IS GENERATED in this instance, - // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter - // for the peer that it uses LESS bits to represent the message. - return m_iMsgNoBitset & MSGNO_SEQ::mask; - } - - } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; - - // m_pBlock: The head pointer - // m_pFirstBlock: The first block - // m_pCurrBlock: The current block - // m_pLastBlock: The last block (if first == last, buffer is empty) - - struct Buffer - { - char* m_pcData; // buffer - int m_iSize; // size - Buffer* m_pNext; // next buffer - } * m_pBuffer; // physical buffer - - int32_t m_iNextMsgNo; // next message number - - int m_iSize; // buffer size (number of packets) - const int m_iBlockLen; // maximum length of a block holding packet payload (excluding packet header). - int m_iCount; // number of used blocks - - int m_iBytesCount; // number of payload bytes in queue - time_point m_tsLastOriginTime; - - AvgBufSize m_mavg; - CRateEstimator m_rateEstimator; - -private: - CSndBuffer(const CSndBuffer&); - CSndBuffer& operator=(const CSndBuffer&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -#if (!ENABLE_NEW_RCVBUFFER) - -class CRcvBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the queue is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - static const int DEFAULT_SIZE = 65536; - /// Construct the buffer. - /// @param [in] queue CUnitQueue that actually holds the units (packets) - /// @param [in] bufsize_pkts in units (packets) - CRcvBuffer(CUnitQueue* queue, int bufsize_pkts = DEFAULT_SIZE); - ~CRcvBuffer(); - -public: - /// Write data into the buffer. - /// @param [in] unit pointer to a data unit containing new packet - /// @param [in] offset offset from last ACK point. - /// @return 0 is success, -1 if data is repeated. - int addData(CUnit* unit, int offset); - - /// Read data into a user buffer. - /// @param [in] data pointer to user buffer. - /// @param [in] len length of user buffer. - /// @return size of data read. - int readBuffer(char* data, int len); - - /// Read data directly into file. - /// @param [in] file C++ file stream. - /// @param [in] len expected length of data to write into the file. - /// @return size of data read. - int readBufferToFile(std::fstream& ofs, int len); - - /// Update the ACK point of the buffer. - /// @param [in] len number of units to be acknowledged. - /// @return 1 if a user buffer is fulfilled, otherwise 0. - int ackData(int len); - - /// Query how many buffer space left for data receiving. - /// Actually only acknowledged packets, that are still in the buffer, - /// are considered to take buffer space. - /// - /// @return size of available buffer space (including user buffer) for data receiving. - /// Not counting unacknowledged packets. - int getAvailBufSize() const; - - /// Query how many data has been continuously received (for reading) and ready to play (tsbpdtime < now). - /// @return size of valid (continous) data for reading. - int getRcvDataSize() const; - - /// Query how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvDataSize(int& bytes, int& spantime); - - /// Query a 1 sec moving average of how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvAvgDataSize(int& bytes, int& spantime); - - /// Query how many data of the receive buffer is acknowledged. - /// @param [in] now current time in us. - /// @return none. - void updRcvAvgDataSize(const time_point& now); - - /// Query the received average payload size. - /// @return size (bytes) of payload size - unsigned getRcvAvgPayloadSize() const; - - struct ReadingState - { - time_point tsStart; - time_point tsLastAck; - time_point tsEnd; - int iNumAcknowledged; - int iNumUnacknowledged; - }; - - ReadingState debugGetReadingState() const; - - /// Form a string of the current buffer fullness state. - /// number of packets acknowledged, TSBPD readiness, etc. - std::string strFullnessState(const time_point& tsNow) const; - - /// Mark the message to be dropped from the message list. - /// @param [in] msgno message number. - /// @param [in] using_rexmit_flag whether the MSGNO field uses rexmit flag (if not, one more bit is part of the - /// msgno value) - void dropMsg(int32_t msgno, bool using_rexmit_flag); - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @return actuall size of data read. - int readMsg(char* data, int len); - -#if ENABLE_HEAVY_LOGGING - void readMsgHeavyLogging(int p); -#endif - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// @return actuall size of data read. - int readMsg(char* data, int len, SRT_MSGCTRL& w_mctrl, int upto); - - /// Query if data is ready to read (tsbpdtime <= now if TsbPD is active). - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// of next packet in recv buffer, ready or not. - /// @param [out] curpktseq Sequence number of the packet if there is one ready to play - /// @return true if ready to play, false otherwise (tsbpdtime may be !0 in - /// both cases). - bool isRcvDataReady(time_point& w_tsbpdtime, int32_t& w_curpktseq, int32_t seqdistance); - -#ifdef SRT_DEBUG_TSBPD_OUTJITTER - void debugTraceJitter(time_point t); -#else - void debugTraceJitter(time_point) {} -#endif /* SRT_DEBUG_TSBPD_OUTJITTER */ - - bool isRcvDataReady(); - bool isRcvDataAvailable() { return m_iLastAckPos != m_iStartPos; } - CPacket* getRcvReadyPacket(int32_t seqdistance); - - /// Set TimeStamp-Based Packet Delivery Rx Mode - /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay - /// @param [in] delay aggreed TsbPD delay - void setRcvTsbPdMode(const time_point& timebase, const duration& delay); - - /// Add packet timestamp for drift caclculation and compensation - /// @param [in] timestamp packet time stamp - /// @param [in] tsPktArrival arrival time of the packet used to extract the drift sample. - /// @param [in] rtt RTT sample - bool addRcvTsbPdDriftSample(uint32_t timestamp, const time_point& tsPktArrival, int rtt); - -#ifdef SRT_DEBUG_TSBPD_DRIFT - void printDriftHistogram(int64_t iDrift); - void printDriftOffset(int tsbPdOffset, int tsbPdDriftAvg); -#endif - - /// Get information on the 1st message in queue. - // Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] w_tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 - /// if none - /// @param [out] w_passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] w_skipseqno SRT_SEQNO_NONE or seq number of 1st unacknowledged pkt ready to play preceeded by - /// missing packets. - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base if exist packet ready-to-play - /// and larger than base - /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true - /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != SRT_SEQNO_NONE, packet ready to play preceeded by missing packets.; - /// IF skipseqno == SRT_SEQNO_NONE, no missing packet but 1st not ready to play. - bool getRcvFirstMsg(time_point& w_tsbpdtime, - bool& w_passack, - int32_t& w_skipseqno, - int32_t& w_curpktseq, - int32_t base_seq = SRT_SEQNO_NONE); - - /// Update the ACK point of the buffer. - /// @param [in] len size of data to be skip & acknowledged. - void skipData(int len); - -#if ENABLE_HEAVY_LOGGING - void reportBufferStats() const; // Heavy logging Debug only -#endif - bool empty() const - { - // This will not always return the intended value, - // that is, it may return false when the buffer really is - // empty - but it will return true then in one of next calls. - // This function will be always called again at some point - // if it returned false, and on true the connection - // is going to be broken - so this behavior is acceptable. - return m_iStartPos == m_iLastAckPos; - } - bool full() const { return m_iStartPos == (m_iLastAckPos + 1) % m_iSize; } - int capacity() const { return m_iSize; } - -private: - /// This gives up unit at index p. The unit is given back to the - /// free unit storage for further assignment for the new incoming - /// data. - size_t freeUnitAt(size_t p) - { - CUnit* u = m_pUnit[p]; - m_pUnit[p] = NULL; - size_t rmbytes = u->m_Packet.getLength(); - m_pUnitQueue->makeUnitFree(u); - return rmbytes; - } - - /// Adjust receive queue to 1st ready to play message (tsbpdtime < now). - /// Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if - /// none - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base - /// @retval true 1st packet ready to play without discontinuity (no hole) - /// @retval false tsbpdtime = 0: no packet ready to play - bool getRcvReadyMsg(time_point& w_tsbpdtime, int32_t& w_curpktseq, int upto, int base_seq = SRT_SEQNO_NONE); - -public: - /// @brief Get clock drift in microseconds. - int64_t getDrift() const { return m_tsbpd.drift(); } - -public: - int32_t getTopMsgno() const; - - void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift); - - void applyGroupTime(const time_point& timebase, bool wrapcheck, uint32_t delay, const duration& udrift); - void applyGroupDrift(const time_point& timebase, bool wrapcheck, const duration& udrift); - time_point getPktTsbPdTime(uint32_t timestamp); - int debugGetSize() const; - time_point debugGetDeliveryTime(int offset); - - size_t dropData(int len); - -private: - int extractData(char* data, int len, int p, int q, bool passack); - bool accessMsg(int& w_p, int& w_q, bool& w_passack, int64_t& w_playtime, int upto); - - /// Describes the state of the first N packets - std::string debugTimeState(size_t first_n_pkts) const; - - /// thread safe bytes counter of the Recv & Ack buffer - /// @param [in] pkts acked or removed pkts from rcv buffer (used with acked = true) - /// @param [in] bytes number of bytes added/delete (if negative) to/from rcv buffer. - /// @param [in] acked true when adding new pkt in RcvBuffer; false when acking/removing pkts to/from buffer - void countBytes(int pkts, int bytes, bool acked = false); - -private: - bool scanMsg(int& w_start, int& w_end, bool& w_passack); - - int shift(int basepos, int shift) const { return (basepos + shift) % m_iSize; } - - /// Simplified versions with ++ and --; avoid using division instruction - int shiftFwd(int basepos) const - { - if (++basepos == m_iSize) - return 0; - return basepos; - } - - int shiftBack(int basepos) const - { - if (basepos == 0) - return m_iSize - 1; - return --basepos; - } - -private: - CUnit** m_pUnit; // Array of pointed units collected in the buffer - const int m_iSize; // Size of the internal array of CUnit* items - CUnitQueue* m_pUnitQueue; // the shared unit queue - - int m_iStartPos; // HEAD: first packet available for reading - int m_iLastAckPos; // the last ACKed position (exclusive), follows the last readable - // EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1 - int m_iMaxPos; // delta between acked-TAIL and reception-TAIL - - int m_iNotch; // the starting read point of the first unit - // (this is required for stream reading mode; it's - // the position in the first unit in the list - // up to which data are already retrieved; - // in message reading mode it's unused and always 0) - - sync::Mutex m_BytesCountLock; // used to protect counters operations - int m_iBytesCount; // Number of payload bytes in the buffer - int m_iAckedPktsCount; // Number of acknowledged pkts in the buffer - int m_iAckedBytesCount; // Number of acknowledged payload bytes in the buffer - unsigned m_uAvgPayloadSz; // Average payload size for dropped bytes estimation - - CTsbpdTime m_tsbpd; - - AvgBufSize m_mavg; - -private: - CRcvBuffer(); - CRcvBuffer(const CRcvBuffer&); - CRcvBuffer& operator=(const CRcvBuffer&); -}; - -#endif // !ENABLE_NEW_RCVBUFFER - -} // namespace srt - -#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_rcv.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_rcv.h index d628c459f..d4b50fab7 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_rcv.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_rcv.h @@ -11,12 +11,9 @@ #ifndef INC_SRT_BUFFER_RCV_H #define INC_SRT_BUFFER_RCV_H -#if ENABLE_NEW_RCVBUFFER - -#include "buffer.h" // AvgBufSize +#include "buffer_tools.h" // AvgBufSize #include "common.h" #include "queue.h" -#include "sync.h" #include "tsbpd_time.h" namespace srt @@ -26,7 +23,7 @@ namespace srt * Circular receiver buffer. * * |<------------------- m_szSize ---------------------------->| - * | |<------------ m_iMaxPosInc ----------->| | + * | |<------------ m_iMaxPosOff ----------->| | * | | | | * +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+ * | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |...| 0 | m_pUnit[] @@ -45,15 +42,15 @@ namespace srt * first_nonread_pos_: */ -class CRcvBufferNew +class CRcvBuffer { typedef sync::steady_clock::time_point time_point; typedef sync::steady_clock::duration duration; public: - CRcvBufferNew(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); + CRcvBuffer(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); - ~CRcvBufferNew(); + ~CRcvBuffer(); public: /// Insert a unit into the buffer. @@ -77,14 +74,29 @@ class CRcvBufferNew /// @return the number of dropped packets. int dropAll(); - /// @brief Drop the whole message from the buffer. - /// If message number is 0, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. - /// When one packet of the message is in the range of dropping, the whole message is to be dropped. + enum DropActionIfExists { + DROP_EXISTING = 0, + KEEP_EXISTING = 1 + }; + + /// @brief Drop a sequence of packets from the buffer. + /// If @a msgno is valid, sender has requested to drop the whole message by TTL. In this case it has to also provide a pkt seqno range. + /// However, if a message has been partially acknowledged and already removed from the SND buffer, + /// the @a seqnolo might specify some position in the middle of the message, not the very first packet. + /// If those packets have been acknowledged, they must exist in the receiver buffer unless already read. + /// In this case the @a msgno should be used to determine starting packets of the message. + /// Some packets of the message can be missing on the receiver, therefore the actual drop should still be performed by pkt seqno range. + /// If message number is 0 or SRT_MSGNO_NONE, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. + /// A SOLO message packet can be kept depending on @a actionOnExisting value. + /// TODO: A message in general can be kept if all of its packets are in the buffer, depending on @a actionOnExisting value. + /// This is done to avoid dropping existing packet when the sender was asked to re-transmit a packet from an outdated loss report, + /// which is already not available in the SND buffer. /// @param seqnolo sequence number of the first packet in the dropping range. /// @param seqnohi sequence number of the last packet in the dropping range. /// @param msgno message number to drop (0 if unknown) + /// @param actionOnExisting Should an exising SOLO packet be dropped from the buffer or preserved? /// @return the number of packets actually dropped. - int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno); + int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno, DropActionIfExists actionOnExisting); /// Read the whole message from one or several packets. /// @@ -130,9 +142,8 @@ class CRcvBufferNew const int iRBufSeqNo = getStartSeqNo(); if (CSeqNo::seqcmp(iRBufSeqNo, iFirstUnackSeqNo) >= 0) // iRBufSeqNo >= iFirstUnackSeqNo { - // Full capacity is available, still don't want to encourage extra packets to come. - // Note: CSeqNo::seqlen(n, n) returns 1. - return capacity() - CSeqNo::seqlen(iFirstUnackSeqNo, iRBufSeqNo) + 1; + // Full capacity is available. + return capacity(); } // Note: CSeqNo::seqlen(n, n) returns 1. @@ -140,13 +151,14 @@ class CRcvBufferNew } /// @brief Checks if the buffer has packets available for reading regardless of the TSBPD. + /// A message is available for reading only if all of its packets are present in the buffer. /// @return true if there are packets available for reading, false otherwise. bool hasAvailablePackets() const; /// Query how many data has been continuously received (for reading) and available for reading out /// regardless of the TSBPD. /// TODO: Rename to countAvailablePackets(). - /// @return size of valid (continous) data for reading. + /// @return size of valid (continuous) data for reading. int getRcvDataSize() const; /// Get the number of packets, bytes and buffer timespan. @@ -165,11 +177,11 @@ class CRcvBufferNew /// Parameters (of the 1st packet queue, ready to play or not): /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if /// none - /// @param [out] passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] skipseqno -1 or seq number of 1st unacknowledged pkt ready to play preceeded by missing packets. + /// @param [out] passack true if 1st ready packet is not yet acknowledged (allowed to be delivered to the app) + /// @param [out] skipseqno -1 or sequence number of 1st unacknowledged packet (after one or more missing packets) that is ready to play. /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != -1, packet ready to play preceeded by missing packets.; + /// IF skipseqno != -1, packet ready to play preceded by missing packets.; /// IF skipseqno == -1, no missing packet but 1st not ready to play. PacketInfo getFirstValidPacketInfo() const; @@ -185,7 +197,7 @@ class CRcvBufferNew bool empty() const { - return (m_iMaxPosInc == 0); + return (m_iMaxPosOff == 0); } /// Return buffer capacity. @@ -227,6 +239,18 @@ class CRcvBufferNew inline int incPos(int pos, int inc = 1) const { return (pos + inc) % m_szSize; } inline int decPos(int pos) const { return (pos - 1) >= 0 ? (pos - 1) : int(m_szSize - 1); } inline int offPos(int pos1, int pos2) const { return (pos2 >= pos1) ? (pos2 - pos1) : int(m_szSize + pos2 - pos1); } + inline int cmpPos(int pos2, int pos1) const + { + // XXX maybe not the best implementation, but this keeps up to the rule + const int off1 = pos1 >= m_iStartPos ? pos1 - m_iStartPos : pos1 + (int)m_szSize - m_iStartPos; + const int off2 = pos2 >= m_iStartPos ? pos2 - m_iStartPos : pos2 + (int)m_szSize - m_iStartPos; + + return off2 - off1; + } + + // NOTE: Assumes that pUnit != NULL + CPacket& packetAt(int pos) { return m_entries[pos].pUnit->m_Packet; } + const CPacket& packetAt(int pos) const { return m_entries[pos].pUnit->m_Packet; } private: void countBytes(int pkts, int bytes); @@ -268,7 +292,7 @@ class CRcvBufferNew int getTimespan_ms() const; private: - // TODO: Call makeUnitGood upon assignment, and makeUnitFree upon clearing. + // TODO: Call makeUnitTaken upon assignment, and makeUnitFree upon clearing. // TODO: CUnitPtr is not in use at the moment, but may be a smart pointer. // class CUnitPtr // { @@ -313,7 +337,7 @@ class CRcvBufferNew int m_iStartSeqNo; int m_iStartPos; // the head position for I/O (inclusive) int m_iFirstNonreadPos; // First position that can't be read (<= m_iLastAckPos) - int m_iMaxPosInc; // the furthest data position + int m_iMaxPosOff; // the furthest data position int m_iNotch; // the starting read point of the first unit size_t m_numOutOfOrderPackets; // The number of stored packets with "inorder" flag set to false @@ -326,7 +350,7 @@ class CRcvBufferNew /// Set TimeStamp-Based Packet Delivery Rx Mode /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay /// @param [in] wrap Is in wrapping period - /// @param [in] delay aggreed TsbPD delay + /// @param [in] delay agreed TsbPD delay /// /// @return 0 void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); @@ -344,6 +368,8 @@ class CRcvBufferNew time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; void updateTsbPdTimeBase(uint32_t usPktTimestamp); + bool isTsbPd() const { return m_tsbpd.isEnabled(); } + /// Form a string of the current buffer fullness state. /// number of packets acknowledged, TSBPD readiness, etc. std::string strFullnessState(int iFirstUnackSeqNo, const time_point& tsNow) const; @@ -363,5 +389,4 @@ class CRcvBufferNew } // namespace srt -#endif // ENABLE_NEW_RCVBUFFER #endif // INC_SRT_BUFFER_RCV_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_snd.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_snd.h new file mode 100644 index 000000000..4440b9bfd --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_snd.h @@ -0,0 +1,259 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_SND_H +#define INC_SRT_BUFFER_SND_H + +#include "srt.h" +#include "packet.h" +#include "buffer_tools.h" + +// The notation used for "circular numbers" in comments: +// The "cicrular numbers" are numbers that when increased up to the +// maximum become zero, and similarly, when the zero value is decreased, +// it turns into the maximum value minus one. This wrapping works the +// same for adding and subtracting. Circular numbers cannot be multiplied. + +// Operations done on these numbers are marked with additional % character: +// a %> b : a is later than b +// a ++% (++%a) : shift a by 1 forward +// a +% b : shift a by b +// a == b : equality is same as for just numbers + +namespace srt { + +class CSndBuffer +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the buffer is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// @brief CSndBuffer constructor. + /// @param size initial number of blocks (each block to store one packet payload). + /// @param maxpld maximum packet payload (including auth tag). + /// @param authtag auth tag length in bytes (16 for GCM, 0 otherwise). + CSndBuffer(int size = 32, int maxpld = 1500, int authtag = 0); + ~CSndBuffer(); + +public: + /// Insert a user buffer into the sending list. + /// For @a w_mctrl the following fields are used: + /// INPUT: + /// - msgttl: timeout for retransmitting the message, if lost + /// - inorder: request to deliver the message in order of sending + /// - srctime: local time as a base for packet's timestamp (0 if unused) + /// - pktseq: sequence number to be stamped on the packet (-1 if unused) + /// - msgno: message number to be stamped on the packet (-1 if unused) + /// OUTPUT: + /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) + /// - pktseq: sequence number to be stamped on the next packet + /// - msgno: message number stamped on the packet + /// @param [in] data pointer to the user data block. + /// @param [in] len size of the block. + /// @param [inout] w_mctrl Message control data + SRT_ATTR_EXCLUDES(m_BufLock) + void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); + + /// Read a block of data from file and insert it into the sending list. + /// @param [in] ifs input file stream. + /// @param [in] len size of the block. + /// @return actual size of data added from the file. + SRT_ATTR_EXCLUDES(m_BufLock) + int addBufferFromFile(std::fstream& ifs, int len); + + /// Find data position to pack a DATA packet from the furthest reading point. + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [in] kflags Odd|Even crypto key flag + /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. + /// @return Actual length of data read. + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); + + /// Peek an information on the next original data packet to send. + /// @return origin time stamp of the next packet; epoch start time otherwise. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point peekNextOriginal() const; + + /// Find data position to pack a DATA packet for a retransmission. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [out] msglen length of the message + /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); + + /// Get the time of the last retransmission (if any) of the DATA packet. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// + /// @return Last time of the last retransmission event for the corresponding DATA packet. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point getPacketRexmitTime(const int offset); + + /// Update the ACK point and may release/unmap/return the user data according to the flag. + /// @param [in] offset number of packets acknowledged. + int32_t getMsgNoAt(const int offset); + + void ackData(int offset); + + /// Read size of data still in the sending list. + /// @return Current size of the data in the sending list. + int getCurrBufSize() const; + + SRT_ATTR_EXCLUDES(m_BufLock) + int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); + + void updAvgBufSize(const time_point& time); + int getAvgBufSize(int& bytes, int& timespan); + int getCurrBufSize(int& bytes, int& timespan) const; + + + /// Het maximum payload length per packet. + int getMaxPacketLen() const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen) const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @param iMaxPktLen the maximum payload length of the packet (the value returned from getMaxPacketLen()). + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen, int iMaxPktLen) const; + + /// @brief Get the buffering delay of the oldest message in the buffer. + /// @return the delay value. + SRT_ATTR_EXCLUDES(m_BufLock) + duration getBufferingDelay(const time_point& tnow) const; + + uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_rateEstimator.getInputRate(); } + + void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } + + const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } + + void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } + +private: + void increase(); + +private: + mutable sync::Mutex m_BufLock; // used to synchronize buffer operation + + struct Block + { + char* m_pcData; // pointer to the data block + int m_iLength; // payload length of the block (excluding auth tag). + + int32_t m_iMsgNoBitset; // message number + int32_t m_iSeqNo; // sequence number for scheduling + time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. + time_point m_tsRexmitTime; // packet retransmission time + int m_iTTL; // time to live (milliseconds) + + Block* m_pNext; // next block + + int32_t getMsgSeq() + { + // NOTE: this extracts message ID with regard to REXMIT flag. + // This is valid only for message ID that IS GENERATED in this instance, + // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter + // for the peer that it uses LESS bits to represent the message. + return m_iMsgNoBitset & MSGNO_SEQ::mask; + } + + } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; + + // m_pBlock: The head pointer + // m_pFirstBlock: The first block + // m_pCurrBlock: The current block + // m_pLastBlock: The last block (if first == last, buffer is empty) + + struct Buffer + { + char* m_pcData; // buffer + int m_iSize; // size + Buffer* m_pNext; // next buffer + } * m_pBuffer; // physical buffer + + int32_t m_iNextMsgNo; // next message number + + int m_iSize; // buffer size (number of packets) + const int m_iBlockLen; // maximum length of a block holding packet payload and AUTH tag (excluding packet header). + const int m_iAuthTagSize; // Authentication tag size (if GCM is enabled). + int m_iCount; // number of used blocks + + int m_iBytesCount; // number of payload bytes in queue + time_point m_tsLastOriginTime; + + AvgBufSize m_mavg; + CRateEstimator m_rateEstimator; + +private: + CSndBuffer(const CSndBuffer&); + CSndBuffer& operator=(const CSndBuffer&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_tools.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_tools.h new file mode 100644 index 000000000..e6ce89d0d --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/buffer_tools.h @@ -0,0 +1,201 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_TOOLS_H +#define INC_SRT_BUFFER_TOOLS_H + +#include "common.h" + +namespace srt +{ + +/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) +class AvgBufSize +{ + typedef sync::steady_clock::time_point time_point; + +public: + AvgBufSize() + : m_dBytesCountMAvg(0.0) + , m_dCountMAvg(0.0) + , m_dTimespanMAvg(0.0) + { + } + +public: + bool isTimeToUpdate(const time_point& now) const; + void update(const time_point& now, int pkts, int bytes, int timespan_ms); + +public: + inline double pkts() const { return m_dCountMAvg; } + inline double timespan_ms() const { return m_dTimespanMAvg; } + inline double bytes() const { return m_dBytesCountMAvg; } + +private: + time_point m_tsLastSamplingTime; + double m_dBytesCountMAvg; + double m_dCountMAvg; + double m_dTimespanMAvg; +}; + +/// The class to estimate source bitrate based on samples submitted to the buffer. +/// Is currently only used by the CSndBuffer. +class CRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; +public: + CRateEstimator(); + +public: + uint64_t getInRatePeriod() const { return m_InRatePeriod; } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_iInRateBps; } + + void setInputRateSmpPeriod(int period); + + /// Update input rate calculation. + /// @param [in] time current time + /// @param [in] pkts number of packets newly added to the buffer + /// @param [in] bytes number of payload bytes in those newly added packets + void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); + + void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } + +private: // Constants + static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms + static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms + static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload + static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; + +private: + int m_iInRatePktsCount; // number of payload packets added since InRateStartTime. + int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime. + time_point m_tsInRateStartTime; + uint64_t m_InRatePeriod; // usec + int m_iInRateBps; // Input Rate in Bytes/sec +}; + + +class CSndRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + +public: + CSndRateEstimator(const time_point& tsNow); + + /// Add sample. + /// @param [in] time sample (sending) time. + /// @param [in] pkts number of packets in the sample. + /// @param [in] bytes number of payload bytes in the sample. + void addSample(const time_point& time, int pkts = 0, size_t bytes = 0); + + /// Retrieve estimated bitrate in bytes per second + int getRate() const { return m_iRateBps; } + + /// Retrieve estimated bitrate in bytes per second inluding the current sampling interval. + int getCurrentRate() const; + +private: + static const int NUM_PERIODS = 10; + static const int SAMPLE_DURATION_MS = 100; // 100 ms + struct Sample + { + int m_iPktsCount; // number of payload packets + int m_iBytesCount; // number of payload bytes + + void reset() + { + m_iPktsCount = 0; + m_iBytesCount = 0; + } + + Sample() + : m_iPktsCount(0) + , m_iBytesCount(0) + { + } + + Sample(int iPkts, int iBytes) + : m_iPktsCount(iPkts) + , m_iBytesCount(iBytes) + { + } + + Sample operator+(const Sample& other) + { + return Sample(m_iPktsCount + other.m_iPktsCount, m_iBytesCount + other.m_iBytesCount); + } + + Sample& operator+=(const Sample& other) + { + *this = *this + other; + return *this; + } + + bool empty() const { return m_iPktsCount == 0; } + }; + + int incSampleIdx(int val, int inc = 1) const; + + Sample m_Samples[NUM_PERIODS]; + + time_point m_tsFirstSampleTime; //< Start time of the first sameple. + int m_iFirstSampleIdx; //< Index of the first sample. + int m_iCurSampleIdx; //< Index of the current sample being collected. + int m_iRateBps; // Input Rate in Bytes/sec +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/cache.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/cache.h index 0dd57ba01..47633706a 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/cache.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/cache.h @@ -253,7 +253,7 @@ class CInfoBlock CInfoBlock& copyFrom(const CInfoBlock& obj); CInfoBlock(const CInfoBlock& src) { copyFrom(src); } CInfoBlock& operator=(const CInfoBlock& src) { return copyFrom(src); } - bool operator==(const CInfoBlock& obj); + bool operator==(const CInfoBlock& obj) const; CInfoBlock* clone(); int getKey(); void release() {} diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/channel.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/channel.h index 0255102fe..1bfcc47c8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/channel.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/channel.h @@ -115,9 +115,10 @@ class CChannel /// Send a packet to the given address. /// @param [in] addr pointer to the destination address. /// @param [in] packet reference to a CPacket entity. + /// @param [in] src source address to sent on an outgoing packet (if not ANY) /// @return Actual size of data sent. - int sendto(const sockaddr_any& addr, srt::CPacket& packet) const; + int sendto(const sockaddr_any& addr, srt::CPacket& packet, const sockaddr_any& src) const; /// Receive a packet from the channel and record the source address. /// @param [in] addr pointer to the source address. @@ -128,6 +129,21 @@ class CChannel void setConfig(const CSrtMuxerConfig& config); + void getSocketOption(int level, int sockoptname, char* pw_dataptr, socklen_t& w_len, int& w_status); + + template + Type sockopt(int level, int sockoptname, Type deflt) + { + Type retval; + socklen_t socklen = sizeof retval; + int status; + getSocketOption(level, sockoptname, ((char*)&retval), (socklen), (status)); + if (status == -1) + return deflt; + + return retval; + } + /// Get the IP TTL. /// @param [in] ttl IP Time To Live. /// @return TTL. @@ -160,6 +176,121 @@ class CChannel // although the object itself isn't considered modified. mutable CSrtMuxerConfig m_mcfg; // Note: ReuseAddr is unused and ineffective. sockaddr_any m_BindAddr; + + // This feature is not enabled on Windows, for now. + // This is also turned off in case of MinGW +#ifdef SRT_ENABLE_PKTINFO + bool m_bBindMasked; // True if m_BindAddr is INADDR_ANY. Need for quick check. + + // Calculating the required space is extremely tricky, and whereas on most + // platforms it's possible to define it this way: + // + // size_t s = max( CMSG_SPACE(sizeof(in_pktinfo)), CMSG_SPACE(sizeof(in6_pktinfo)) ) + // + // ...on some platforms however CMSG_SPACE macro can't be resolved as constexpr. + // + // This structure is exclusively used to determine the required size for + // CMSG buffer so that it can be allocated in a solid block with CChannel. + // NOT TO BE USED to access any data inside the CMSG message. + struct CMSGNodeIPv4 + { + in_pktinfo in4; + size_t extrafill; + cmsghdr hdr; + }; + + struct CMSGNodeIPv6 + { + in6_pktinfo in6; + size_t extrafill; + cmsghdr hdr; + }; + + // This is 'mutable' because it's a utility buffer defined here + // to avoid unnecessary re-allocations. + mutable char m_acCmsgRecvBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + mutable char m_acCmsgSendBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just after + // calling ::recvmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in receiving mode. + sockaddr_any getTargetAddress(const msghdr& msg) const + { + // Loop through IP header messages + cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(((msghdr*)&msg), cmsg)) + { + // This should be safe - this packet contains always either + // IPv4 headers or IPv6 headers. + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) + { + in_pktinfo *dest_ip_ptr = (in_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi_addr, 0); + } + + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + in6_pktinfo* dest_ip_ptr = (in6_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi6_addr, 0); + } + } + + // Fallback for an error + return sockaddr_any(m_BindAddr.family()); + } + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just before + // calling ::sendmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in sending mode. + bool setSourceAddress(msghdr& mh, const sockaddr_any& adr) const + { + // In contrast to an advice followed on the net, there's no case of putting + // both IPv4 and IPv6 ancillary data, case we could have them. Only one + // IP version is used and it's the version as found in @a adr, which should + // be the version used for binding. + + if (adr.family() == AF_INET) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + // after initializing msghdr & control data to CMSG_SPACE(sizeof(struct in_pktinfo)) + cmsg_send->cmsg_level = IPPROTO_IP; + cmsg_send->cmsg_type = IP_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + in_pktinfo* pktinfo = (in_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi_ifindex = 0; + pktinfo->ipi_spec_dst = adr.sin.sin_addr; + + return true; + } + + if (adr.family() == AF_INET6) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in6_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + cmsg_send->cmsg_level = IPPROTO_IPV6; + cmsg_send->cmsg_type = IPV6_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); + in6_pktinfo* pktinfo = (in6_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi6_ifindex = 0; + pktinfo->ipi6_addr = adr.sin6.sin6_addr; + + return true; + } + + return false; + } + +#endif // SRT_ENABLE_PKTINFO + }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/common.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/common.h index 227a91861..5021fa5a8 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/common.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/common.h @@ -53,7 +53,6 @@ modified by #ifndef INC_SRT_COMMON_H #define INC_SRT_COMMON_H -#define _CRT_SECURE_NO_WARNINGS 1 // silences windows complaints for sscanf #include #include #include @@ -1393,8 +1392,11 @@ inline ATR_CONSTEXPR uint32_t SrtVersion(int major, int minor, int patch) inline int32_t SrtParseVersion(const char* v) { int major, minor, patch; +#if defined(_MSC_VER) + int result = sscanf_s(v, "%d.%d.%d", &major, &minor, &patch); +#else int result = sscanf(v, "%d.%d.%d", &major, &minor, &patch); - +#endif if (result != 3) { return 0; @@ -1409,12 +1411,16 @@ inline std::string SrtVersionString(int version) int minor = (version/0x100)%0x100; int major = version/0x10000; - char buf[20]; - sprintf(buf, "%d.%d.%d", major, minor, patch); + char buf[22]; +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(buf, sizeof(buf) - 1, "%d.%d.%d", major, minor, patch); +#else + snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch); +#endif return buf; } -bool SrtParseConfig(std::string s, SrtConfig& w_config); +bool SrtParseConfig(const std::string& s, SrtConfig& w_config); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/congctl.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/congctl.h index b957dbdd0..a2264b594 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/congctl.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/congctl.h @@ -52,8 +52,8 @@ class SrtCongestion struct IsName { - std::string n; - IsName(std::string nn): n(nn) {} + const std::string n; + IsName(const std::string& nn): n(nn) {} bool operator()(NamePtr np) { return n == np.first; } }; diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/core.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/core.h index fa58ca7c2..71c955c33 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/core.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/core.h @@ -59,7 +59,7 @@ modified by #include "srt.h" #include "common.h" #include "list.h" -#include "buffer.h" +#include "buffer_snd.h" #include "buffer_rcv.h" #include "window.h" #include "packet.h" @@ -288,7 +288,7 @@ class CUDT { #if ENABLE_LOGGING std::ostringstream os; - os << "@" << m_SocketID << ":"; + os << "@" << m_SocketID << ": "; return os.str(); #else return ""; @@ -312,8 +312,10 @@ class CUDT int32_t schedSeqNo() const { return m_iSndNextSeqNo; } bool overrideSndSeqNo(int32_t seq); +#if ENABLE_BONDING sync::steady_clock::time_point lastRspTime() const { return m_tsLastRspTime.load(); } sync::steady_clock::time_point freshActivationStart() const { return m_tsFreshActivation; } +#endif int32_t rcvSeqNo() const { return m_iRcvCurrSeqNo; } int flowWindowSize() const { return m_iFlowWindowSize; } @@ -371,27 +373,34 @@ class CUDT int minSndSize(int len = 0) const { const int ps = (int) maxPayloadSize(); - if (len == 0) // wierd, can't use non-static data member as default argument! + if (len == 0) // weird, can't use non-static data member as default argument! len = ps; return m_config.bMessageAPI ? (len+ps-1)/ps : 1; } - int32_t makeTS(const time_point& from_time) const + static int32_t makeTS(const time_point& from_time, const time_point& tsStartTime) { // NOTE: // - This calculates first the time difference towards start time. // - This difference value is also CUT OFF THE SEGMENT information // (a multiple of MAX_TIMESTAMP+1) // So, this can be simply defined as: TS = (RTS - STS) % (MAX_TIMESTAMP+1) - // XXX Would be nice to check if local_time > m_tsStartTime, - // otherwise it may go unnoticed with clock skew. - return (int32_t) sync::count_microseconds(from_time - m_stats.tsStartTime); + SRT_ASSERT(from_time >= tsStartTime); + return (int32_t) sync::count_microseconds(from_time - tsStartTime); } - void setPacketTS(CPacket& p, const time_point& local_time) - { - p.m_iTimeStamp = makeTS(local_time); - } + /// @brief Set the timestamp field of the packet using the provided value (no check) + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setPacketTS(CPacket& p, const time_point& ts); + + /// @brief Set the timestamp field of the packet according the TSBPD mode. + /// Also checks the connection start time (m_tsStartTime). + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. Ignored if m_bPeerTsbPd is false. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setDataPacketTS(CPacket& p, const time_point& ts); // Utility used for closing a listening socket // immediately to free the socket @@ -416,11 +425,7 @@ class CUDT SRTU_PROPERTY_RO(SRTSOCKET, id, m_SocketID); SRTU_PROPERTY_RO(bool, isClosing, m_bClosing); -#if ENABLE_NEW_RCVBUFFER - SRTU_PROPERTY_RO(srt::CRcvBufferNew*, rcvBuffer, m_pRcvBuffer); -#else - SRTU_PROPERTY_RO(CRcvBuffer*, rcvBuffer, m_pRcvBuffer); -#endif + SRTU_PROPERTY_RO(srt::CRcvBuffer*, rcvBuffer, m_pRcvBuffer); SRTU_PROPERTY_RO(bool, isTLPktDrop, m_bTLPktDrop); SRTU_PROPERTY_RO(bool, isSynReceiving, m_config.bSynRecving); SRTU_PROPERTY_RR(sync::Condition*, recvDataCond, &m_RecvDataCond); @@ -441,16 +446,13 @@ class CUDT private: /// initialize a UDT entity and bind to a local address. - void open(); /// Start listening to any connection request. - void setListenState(); /// Connect to a UDT entity listening at address "peer". /// @param peer [in] The address of the listening UDT entity. - void startConnect(const sockaddr_any& peer, int32_t forced_isn); /// Process the response handshake packet. Failure reasons can be: @@ -461,7 +463,6 @@ class CUDT /// @retval 0 Connection successful /// @retval 1 Connection in progress (m_ConnReq turned into RESPONSE) /// @retval -1 Connection failed - SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processConnectResponse(const CPacket& pkt, CUDTException* eout) ATR_NOEXCEPT; @@ -484,15 +485,20 @@ class CUDT /// @param rst Current read status to know if the HS packet was freshly received from the peer, or this is only a periodic update (RST_AGAIN) SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processRendezvous(const CPacket* response, const sockaddr_any& serv_addr, EReadStatus, CPacket& reqpkt); + void sendRendezvousRejection(const sockaddr_any& serv_addr, CPacket& request); + + /// Create the CryptoControl object based on the HS packet. + SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) + bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException* eout); - /// Create the CryptoControl object based on the HS packet. Allocates sender and receiver buffers and loss lists. + /// Allocates sender and receiver buffers and loss lists. SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) - bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException *eout); + bool prepareBuffers(CUDTException* eout); SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus postConnect(const CPacket* response, bool rendezvous, CUDTException* eout) ATR_NOEXCEPT; - SRT_ATR_NODISCARD bool applyResponseSettings() ATR_NOEXCEPT; + SRT_ATR_NODISCARD bool applyResponseSettings(const CPacket* hspkt /*[[nullable]]*/) ATR_NOEXCEPT; SRT_ATR_NODISCARD EConnectStatus processAsyncConnectResponse(const CPacket& pkt) ATR_NOEXCEPT; SRT_ATR_NODISCARD bool processAsyncConnectRequest(EReadStatus rst, EConnectStatus cst, const CPacket* response, const sockaddr_any& serv_addr); SRT_ATR_NODISCARD EConnectStatus craftKmResponse(uint32_t* aw_kmdata, size_t& w_kmdatasize); @@ -662,8 +668,14 @@ class CUDT /// the receiver fresh loss list. void unlose(const CPacket& oldpacket); void dropFromLossLists(int32_t from, int32_t to); + bool getFirstNoncontSequence(int32_t& w_seq, std::string& w_log_reason); + + SRT_ATTR_EXCLUDES(m_ConnectionLock) + void checkSndTimers(); + + /// @brief Check and perform KM refresh if needed. + void checkSndKMRefresh(); - void checkSndTimers(Whether2RegenKm regen = DONT_REGEN_KM); void handshakeDone() { m_iSndHsRetryCnt = 0; @@ -708,18 +720,17 @@ class CUDT SRT_ATTR_EXCLUDES(m_RcvBufferLock) bool isRcvBufferReady() const; + SRT_ATTR_REQUIRES(m_RcvBufferLock) + bool isRcvBufferReadyNoLock() const; + // TSBPD thread main function. static void* tsbpd(void* param); -#if ENABLE_NEW_RCVBUFFER - /// Drop too late packets (receiver side). Updaet loss lists and ACK positions. + /// Drop too late packets (receiver side). Update loss lists and ACK positions. /// The @a seqno packet itself is not dropped. /// @param seqno [in] The sequence number of the first packets following those to be dropped. /// @return The number of packets dropped. int rcvDropTooLateUpTo(int seqno); -#endif - - void updateForgotten(int seqlen, int32_t lastack, int32_t skiptoseqno); static loss_seqs_t defaultPacketArrival(void* vself, CPacket& pkt); static loss_seqs_t groupPacketArrival(void* vself, CPacket& pkt); @@ -811,6 +822,9 @@ class CUDT CSndBuffer* m_pSndBuffer; // Sender buffer CSndLossList* m_pSndLossList; // Sender loss list CPktTimeWindow<16, 16> m_SndTimeWindow; // Packet sending time window +#ifdef ENABLE_MAXREXMITBW + CSndRateEstimator m_SndRexmitRate; // Retransmission rate estimation. +#endif atomic_duration m_tdSendInterval; // Inter-packet time, in CPU clock cycles @@ -826,6 +840,7 @@ class CUDT duration m_tdACKInterval; // ACK interval duration m_tdNAKInterval; // NAK interval + SRT_ATTR_GUARDED_BY(m_RecvAckLock) atomic_time_point m_tsLastRspTime; // Timestamp of last response from the peer time_point m_tsLastRspAckTime; // (SND) Timestamp of last ACK from the peer @@ -851,7 +866,7 @@ class CUDT // and this is the sequence number that refers to the block at position [0]. Upon acknowledgement, // this value is shifted to the acknowledged position, and the blocks are removed from the // m_pSndBuffer buffer up to excluding this sequence number. - // XXX CONSIDER removing this field and give up the maintenance of this sequence number + // XXX CONSIDER removing this field and giving up the maintenance of this sequence number // to the sending buffer. This way, extraction of an old packet for retransmission should // require only the lost sequence number, and how to find the packet with this sequence // will be up to the sending buffer. @@ -894,14 +909,22 @@ class CUDT SRT_ATTR_GUARDED_BY(m_RecvAckLock) int32_t m_iReXmitCount; // Re-Transmit Count since last ACK + time_point m_tsLogSlowDown; // The last time a log message from the "slow down" group was shown. + // The "slow down" group of logs are those that can be printed too often otherwise, but can't be turned off (warnings and errors). + // Currently only used by decryption failure message, therefore no mutex protection needed. + + /// @brief Check if a frequent log can be shown. + /// @param tnow current time + /// @return true if it is ok to print a frequent log message. + bool frequentLogAllowed(const time_point& tnow) const; + private: // Receiving related data -#if ENABLE_NEW_RCVBUFFER - CRcvBufferNew* m_pRcvBuffer; //< Receiver buffer -#else CRcvBuffer* m_pRcvBuffer; //< Receiver buffer -#endif + SRT_ATTR_GUARDED_BY(m_RcvLossLock) CRcvLossList* m_pRcvLossList; //< Receiver loss list + SRT_ATTR_GUARDED_BY(m_RcvLossLock) std::deque m_FreshLoss; //< Lost sequence already added to m_pRcvLossList, but not yet sent UMSG_LOSSREPORT for. + int m_iReorderTolerance; //< Current value of dynamic reorder tolerance int m_iConsecEarlyDelivery; //< Increases with every OOO packet that came m_iRcvCurrSeqNo; // (RCV) Largest received sequence number. RcvQTh, TSBPDTh. int32_t m_iRcvCurrPhySeqNo; // Same as m_iRcvCurrSeqNo, but physical only (disregarding a filter) - + bool m_bBufferWasFull; // Indicate that RX buffer was full last time a ack was sent int32_t m_iPeerISN; // Initial Sequence Number of the peer side uint32_t m_uPeerSrtVersion; @@ -959,7 +981,7 @@ class CUDT mutable sync::Mutex m_RcvBufferLock; // Protects the state of the m_pRcvBuffer // Protects access to m_iSndCurrSeqNo, m_iSndLastAck - sync::Mutex m_RecvAckLock; // Protects the state changes while processing incomming ACK (SRT_EPOLL_OUT) + sync::Mutex m_RecvAckLock; // Protects the state changes while processing incoming ACK (SRT_EPOLL_OUT) sync::Condition m_RecvDataCond; // used to block "srt_recv*" when there is no data. Use together with m_RecvLock sync::Mutex m_RecvLock; // used to synchronize "srt_recv*" call, protects TSBPD drift updates (CRcvBuffer::isRcvDataReady()) @@ -1036,32 +1058,50 @@ class CUDT void updateSndLossListOnACK(int32_t ackdata_seqno); /// Pack a packet from a list of lost packets. - /// /// @param packet [in, out] a packet structure to fill - /// @param origintime [in, out] origin timestamp of the packet - /// /// @return payload size on success, <=0 on failure - int packLostData(CPacket &packet, time_point &origintime); + int packLostData(CPacket &packet); /// Pack a unique data packet (never sent so far) in CPacket for sending. - /// /// @param packet [in, out] a CPacket structure to fill. - /// @param origintime [in, out] origin timestamp of the packet. /// /// @return true if a packet has been packets; false otherwise. - bool packUniqueData(CPacket& packet, time_point& origintime); + bool packUniqueData(CPacket& packet); /// Pack in CPacket the next data to be send. /// - /// @param packet [in, out] a CPacket structure to fill + /// @param packet [out] a CPacket structure to fill + /// @param nexttime [out] Time when this socket should be next time picked up for processing. + /// @param src_addr [out] Source address to pass to channel's sendto /// - /// @return A pair of values is returned (is_payload_valid, timestamp). - /// If is_payload_valid is false, there was nothing packed for sending, - /// and the timestamp value should be ignored. - /// The timestamp is the full source/origin timestamp of the data. - std::pair packData(CPacket& packet); + /// @retval true A packet was extracted for sending, the socket should be rechecked at @a nexttime + /// @retval false Nothing was extracted for sending, @a nexttime should be ignored + bool packData(CPacket& packet, time_point& nexttime, sockaddr_any& src_addr); int processData(CUnit* unit); + + /// This function passes the incoming packet to the initial processing + /// (like packet filter) and is about to store it effectively to the + /// receiver buffer and do some postprocessing (decryption) if necessary + /// and report the status thereof. + /// + /// @param incoming [in] The packet coming from the network medium + /// @param w_new_inserted [out] Set false, if the packet already exists, otherwise true (packet added) + /// @param w_was_sent_in_order [out] Set false, if the packet was belated, but had no R flag set. + /// @param w_srt_loss_seqs [out] Gets inserted a loss, if this function has detected it. + /// + /// @return 0 The call was successful (regardless if the packet was accepted or not). + /// @return -1 The call has failed: no space left in the buffer. + /// @return -2 The incoming packet exceeds the expected sequence by more than a length of the buffer (irrepairable discrepancy). + int handleSocketPacketReception(const std::vector& incoming, bool& w_new_inserted, bool& w_was_sent_in_order, CUDT::loss_seqs_t& w_srt_loss_seqs); + + /// Get the packet's TSBPD time. + /// The @a grp passed by void* is not used yet + /// and shall not be used when ENABLE_BONDING=0. + time_point getPktTsbPdTime(void* grp, const CPacket& packet); + + /// Checks and spawns the TSBPD thread if required. + int checkLazySpawnTsbPdThread(); void processClose(); /// Process the request after receiving the handshake from caller. @@ -1075,12 +1115,7 @@ class CUDT static void addLossRecord(std::vector& lossrecord, int32_t lo, int32_t hi); int32_t bake(const sockaddr_any& addr, int32_t previous_cookie = 0, int correction = 0); - /// @brief Acknowledge reading position up to the @p seq. - /// Updates m_iRcvLastAck and m_iRcvLastSkipAck to @p seq. - /// @param seq first unacknowledged packet sequence number. - void ackDataUpTo(int32_t seq); - -#if ENABLE_BONDING && ENABLE_NEW_RCVBUFFER +#if ENABLE_BONDING /// @brief Drop packets in the recv buffer behind group_recv_base. /// Updates m_iRcvLastSkipAck if it's behind group_recv_base. void dropToGroupRecvBase(); @@ -1088,9 +1123,6 @@ class CUDT void processKeepalive(const CPacket& ctrlpkt, const time_point& tsArrival); - /// Locks m_RcvBufferLock and retrieves the available size of the receiver buffer. - SRT_ATTR_EXCLUDES(m_RcvBufferLock) - size_t getAvailRcvBufferSizeLock() const; /// Retrieves the available size of the receiver buffer. /// Expects that m_RcvBufferLock is locked. @@ -1120,10 +1152,12 @@ class CUDT static const int PACKETPAIR_MASK = 0xF; private: // Timers functions +#if ENABLE_BONDING time_point m_tsFreshActivation; // GROUPS: time of fresh activation of the link, or 0 if past the activation phase or idle time_point m_tsUnstableSince; // GROUPS: time since unexpected ACK delay experienced, or 0 if link seems healthy time_point m_tsWarySince; // GROUPS: time since an unstable link has first some response - +#endif + static const int BECAUSE_NO_REASON = 0, // NO BITS BECAUSE_ACK = 1 << 0, BECAUSE_LITEACK = 1 << 1, @@ -1142,6 +1176,7 @@ class CUDT CSndQueue* m_pSndQueue; // packet sending queue CRcvQueue* m_pRcvQueue; // packet receiving queue sockaddr_any m_PeerAddr; // peer address + sockaddr_any m_SourceAddr; // override UDP source address with this one when sending uint32_t m_piSelfIP[4]; // local UDP IP address CSNode* m_pSNode; // node information for UDT list used in snd queue CRNode* m_pRNode; // node information for UDT list used in rcv queue diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/crypto.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/crypto.h index 2c2b35250..370d5529c 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/crypto.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/crypto.h @@ -50,8 +50,6 @@ const size_t SRT_KMR_KMSTATE = 0; #define SRT_CMD_MAXSZ HCRYPT_MSG_KM_MAX_SZ /* Maximum SRT custom messages payload size (bytes) */ const size_t SRTDATA_MAXSIZE = SRT_CMD_MAXSZ/sizeof(uint32_t); -enum Whether2RegenKm {DONT_REGEN_KM = 0, REGEN_KM = 1}; - class CCryptoControl { SRTSOCKET m_SocketID; @@ -69,10 +67,12 @@ class CCryptoControl // putting the whole HaiCrypt_Cfg object here. int m_KmRefreshRatePkt; int m_KmPreAnnouncePkt; + int m_iCryptoMode; HaiCrypt_Secret m_KmSecret; //Key material shared secret // Sender sync::steady_clock::time_point m_SndKmLastTime; + sync::Mutex m_mtxLock; // A mutex to protect concurrent access to CCryptoControl. struct { unsigned char Msg[HCRYPT_MSG_KM_MAX_SZ]; size_t MsgLen; @@ -87,6 +87,8 @@ class CCryptoControl public: static void globalInit(); + static bool isAESGCMSupported(); + bool sendingAllowed() { // This function is called to state as to whether the @@ -109,15 +111,16 @@ class CCryptoControl return m_KmSecret.len > 0; } -private: -#ifdef SRT_ENABLE_ENCRYPTION - /// Regenerate cryptographic key material. + int getCryptoMode() const + { + return m_iCryptoMode; + } + + /// Regenerate cryptographic key material if needed. /// @param[in] sock If not null, the socket will be used to send the KM message to the peer (e.g. KM refresh). /// @param[in] bidirectional If true, the key material will be regenerated for both directions (receiver and sender). + SRT_ATTR_EXCLUDES(m_mtxLock) void regenCryptoKm(CUDT* sock, bool bidirectional); -#endif - -public: size_t KeyLen() { return m_iSndKmKeyLen; } @@ -205,13 +208,17 @@ class CCryptoControl std::string FormatKmMessage(std::string hdr, int cmd, size_t srtlen); bool init(HandshakeSide, const CSrtConfig&, bool); + SRT_ATTR_EXCLUDES(m_mtxLock) void close(); - /// @return True if the handshake is in progress. + /// (Re)send KM request to a peer on timeout. /// This function is used in: - /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake) - /// - case of key regeneration, which should be then exchanged again. - void sendKeysToPeer(CUDT* sock, int iSRTT, Whether2RegenKm regen); + /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake). + /// - The case of key regeneration (KM refresh), when a new key has to be sent again. + /// In this case the first sending happens in regenCryptoKm(..). This function + /// retransmits the KM request by timeout if not KM response has been received. + SRT_ATTR_EXCLUDES(m_mtxLock) + void sendKeysToPeer(CUDT* sock, int iSRTT); void setCryptoSecret(const HaiCrypt_Secret& secret) { @@ -224,7 +231,7 @@ class CCryptoControl m_iRcvKmKeyLen = keylen; } - bool createCryptoCtx(size_t keylen, HaiCrypt_CryptoDir tx, HaiCrypt_Handle& rh); + bool createCryptoCtx(HaiCrypt_Handle& rh, size_t keylen, HaiCrypt_CryptoDir tx, bool bAESGCM); int getSndCryptoFlags() const { diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/epoll.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/epoll.h index 7b0d941c8..00d46ceb4 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/epoll.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/epoll.h @@ -69,8 +69,11 @@ class CUDTGroup; class CEPollDesc { +#ifdef __GNUG__ const int m_iID; // epoll ID - +#else + const int m_iID SRT_ATR_UNUSED; // epoll ID +#endif struct Wait; struct Notice: public SRT_EPOLL_EVENT diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/fec.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/fec.h index 71a6adfa7..029709475 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/fec.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/fec.h @@ -47,7 +47,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase size_t drop; //< by how much the sequence should increase to get to the next series size_t collected; //< how many packets were taken to collect the clip - Group(): base(CSeqNo::m_iMaxSeqNo), step(0), drop(0), collected(0) + Group(): base(SRT_SEQNO_NONE), step(0), drop(0), collected(0) { } @@ -87,7 +87,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase #if ENABLE_HEAVY_LOGGING std::string DisplayStats() { - if (base == CSeqNo::m_iMaxSeqNo) + if (base == SRT_SEQNO_NONE) return "UNINITIALIZED!!!"; std::ostringstream os; @@ -222,7 +222,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase void RcvRebuild(Group& g, int32_t seqno, Group::Type tp); int32_t RcvGetLossSeqHoriz(Group& g); int32_t RcvGetLossSeqVert(Group& g); - void EmergencyShrink(size_t n_series); + bool CheckEmergencyShrink(size_t n_series, size_t size_in_packets); static void TranslateLossRecords(const std::set& loss, loss_seqs_t& irrecover); void RcvCheckDismissColumn(int32_t seqno, int colgx, loss_seqs_t& irrecover); diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/group.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/group.h index 1bd84aeda..c2863b44e 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/group.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/group.h @@ -155,7 +155,7 @@ class CUDTGroup srt::sync::ScopedLock g(m_GroupLock); bool empty = false; - HLOGC(gmlog.Debug, log << "group/remove: going to remove @" << id << " from $" << m_GroupID); + LOGC(gmlog.Note, log << "group/remove: removing member @" << id << " from group $" << m_GroupID); gli_t f = std::find_if(m_Group.begin(), m_Group.end(), HaveID(id)); if (f != m_Group.end()) @@ -194,9 +194,6 @@ class CUDTGroup m_bConnected = false; } - // XXX BUGFIX - m_Positions.erase(id); - return !empty; } @@ -265,7 +262,7 @@ class CUDTGroup /// @param[in] pktseq Packet sequence number currently tried to be sent /// @param[out] w_u CUDT unit of the current member (to allow calling overrideSndSeqNo) /// @param[out] w_curseq Group's current sequence number (either -1 or the value used already for other links) - /// @param[out] w_final_stat w_final_stat = send_status if sending succeded. + /// @param[out] w_final_stat w_final_stat = send_status if sending succeeded. /// /// @returns true if the sending operation result (submitted in stat) is a success, false otherwise. bool sendBackup_CheckSendStatus(const time_point& currtime, @@ -406,7 +403,9 @@ class CUDTGroup SRTSOCKET m_PeerGroupID; struct GroupContainer { - std::list m_List; + private: + std::list m_List; + sync::atomic m_SizeCache; /// This field is used only by some types of groups that need /// to keep track as to which link was lately used. Note that @@ -414,8 +413,11 @@ class CUDTGroup /// must be appropriately reset. gli_t m_LastActiveLink; + public: + GroupContainer() - : m_LastActiveLink(m_List.end()) + : m_SizeCache(0) + , m_LastActiveLink(m_List.end()) { } @@ -425,18 +427,18 @@ class CUDTGroup gli_t begin() { return m_List.begin(); } gli_t end() { return m_List.end(); } bool empty() { return m_List.empty(); } - void push_back(const SocketData& data) { m_List.push_back(data); } + void push_back(const SocketData& data) { m_List.push_back(data); ++m_SizeCache; } void clear() { m_LastActiveLink = end(); m_List.clear(); + m_SizeCache = 0; } - size_t size() { return m_List.size(); } + size_t size() { return m_SizeCache; } void erase(gli_t it); }; GroupContainer m_Group; - const bool m_bSyncOnMsgNo; // It goes into a dedicated HS field. Could be true for balancing groups (not implemented). SRT_GROUP_TYPE m_type; CUDTSocket* m_listener; // A "group" can only have one listener. srt::sync::atomic m_iBusy; @@ -641,20 +643,6 @@ class CUDTGroup time_point m_tsStartTime; time_point m_tsRcvPeerStartTime; - struct ReadPos - { - std::vector packet; - SRT_MSGCTRL mctrl; - ReadPos(int32_t s) - : mctrl(srt_msgctrl_default) - { - mctrl.pktseq = s; - } - }; - std::map m_Positions; - - ReadPos* checkPacketAhead(); - void recv_CollectAliveAndBroken(std::vector& w_alive, std::set& w_broken); /// The function polls alive member sockets and retrieves a list of read-ready. @@ -813,7 +801,6 @@ class CUDTGroup SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int32_t, currentSchedSequence, m_iLastSchedSeqNo); SRTU_PROPERTY_RRW(std::set&, epollset, m_sPollID); SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int64_t, latency, m_iTsbPdDelay_us); - SRTU_PROPERTY_RO(bool, synconmsgno, m_bSyncOnMsgNo); SRTU_PROPERTY_RO(bool, closing, m_bClosing); }; diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/list.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/list.h index 03f05e927..8f921c698 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/list.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/list.h @@ -53,6 +53,8 @@ modified by #ifndef INC_SRT_LIST_H #define INC_SRT_LIST_H +#include + #include "udt.h" #include "common.h" @@ -84,6 +86,12 @@ class CSndLossList void traceState() const; + // Debug/unittest support. + + int head() const { return m_iHead; } + int next(int loc) const { return m_caSeq[loc].inext; } + int last() const { return m_iLastInsertPos; } + private: struct Seq { @@ -118,6 +126,8 @@ class CSndLossList /// @param seqno2 last sequence number in range (SRT_SEQNO_NONE if no range) bool updateElement(int pos, int32_t seqno1, int32_t seqno2); + static const int LOC_NONE = -1; + private: CSndLossList(const CSndLossList&); CSndLossList& operator=(const CSndLossList&); @@ -134,8 +144,8 @@ class CRcvLossList /// Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. /// @param [in] seqno1 sequence number starts. /// @param [in] seqno2 seqeunce number ends. - - void insert(int32_t seqno1, int32_t seqno2); + /// @return length of the loss record inserted (seqlen(seqno1, seqno2)), -1 on error. + int insert(int32_t seqno1, int32_t seqno2); /// Remove a loss seq. no. from the receiver's loss list. /// @param [in] seqno sequence number. @@ -150,6 +160,12 @@ class CRcvLossList bool remove(int32_t seqno1, int32_t seqno2); + + /// Remove all numbers that precede the given sequence number. + /// @param [in] seqno sequence number. + /// @return the first removed sequence number + int32_t removeUpTo(int32_t seqno); + /// Find if there is any lost packets whose sequence number falling seqno1 and seqno2. /// @param [in] seqno1 start sequence number. /// @param [in] seqno2 end sequence number. @@ -264,6 +280,8 @@ struct CRcvFreshLoss Emod revoke(int32_t sequence); Emod revoke(int32_t lo, int32_t hi); + + static bool removeOne(std::deque& w_container, int32_t sequence, int* had_ttl = NULL); }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/logging.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/logging.h index e79785b46..e90ad4ac2 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/logging.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/logging.h @@ -60,6 +60,7 @@ written by // LOGF uses printf-like style formatting. // Usage: LOGF(gglog.Debug, "%s: %d", param1.c_str(), int(param2)); +// NOTE: LOGF is deprecated and should not be used #define LOGF(logdes, ...) if (logdes.CheckEnabled()) logdes().setloc(__FILE__, __LINE__, __FUNCTION__).form(__VA_ARGS__) // LOGP is C++11 only OR with only one string argument. @@ -165,14 +166,24 @@ struct SRT_API LogDispatcher // See Logger::Logger; we know this has normally 2 characters, // except !!FATAL!!, which has 9. Still less than 32. - strcpy(prefix, your_pfx); - // If the size of the FA name together with severity exceeds the size, // just skip the former. if (logger_pfx && strlen(prefix) + strlen(logger_pfx) + 1 < MAX_PREFIX_SIZE) { - strcat(prefix, ":"); - strcat(prefix, logger_pfx); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(prefix, MAX_PREFIX_SIZE, "%s:%s", your_pfx, logger_pfx); +#else + snprintf(prefix, MAX_PREFIX_SIZE + 1, "%s:%s", your_pfx, logger_pfx); +#endif + } + else + { +#ifdef _MSC_VER + strncpy_s(prefix, MAX_PREFIX_SIZE + 1, your_pfx, _TRUNCATE); +#else + strncpy(prefix, your_pfx, MAX_PREFIX_SIZE); + prefix[MAX_PREFIX_SIZE] = '\0'; +#endif } } @@ -242,7 +253,9 @@ struct SRT_API LogDispatcher return *this; } - DummyProxy& form(const char*, ...) + // DEPRECATED: DO NOT use LOGF/HLOGF macros anymore. + // Use iostream-style formatting with LOGC or a direct argument with LOGP. + SRT_ATR_DEPRECATED_PX DummyProxy& form(const char*, ...) SRT_ATR_DEPRECATED { return *this; } @@ -356,7 +369,11 @@ struct LogDispatcher::Proxy { char buf[512]; - vsprintf(buf, fmts, ap); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _vsnprintf(buf, sizeof(buf) - 1, fmts, ap); +#else + vsnprintf(buf, sizeof(buf), fmts, ap); +#endif size_t len = strlen(buf); if ( buf[len-1] == '\n' ) { diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/md5.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/md5.h index 98bd07665..643981c01 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/md5.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/md5.h @@ -27,7 +27,7 @@ This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at - http://www.ietf.org/rfc/rfc1321.txt + http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being @@ -38,23 +38,24 @@ that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . + added conditionalization for C++ compilation from Martin + Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED -# define md5_INCLUDED +#define md5_INCLUDED /* * All symbols have been put under the srt namespace * to avoid potential linkage conflicts. */ -namespace srt { +namespace srt +{ /* * This package supports both compile-time and run-time determination of CPU @@ -67,23 +68,24 @@ namespace srt { */ typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; /* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); +void md5_init(md5_state_t* pms); /* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +void md5_append(md5_state_t* pms, const md5_byte_t* data, int nbytes); /* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +void md5_finish(md5_state_t* pms, md5_byte_t digest[16]); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/netinet_any.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/netinet_any.h new file mode 100644 index 000000000..a38765c08 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/netinet_any.h @@ -0,0 +1,426 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_NETINET_ANY_H +#define INC_SRT_NETINET_ANY_H + +#include // memcmp +#include +#include +#include "platform_sys.h" + +// This structure should replace every use of sockaddr and its currently +// used specializations, sockaddr_in and sockaddr_in6. This is to simplify +// the use of the original BSD API that relies on type-violating type casts. +// You can use the instances of sockaddr_any in every place where sockaddr is +// required. + +namespace srt +{ + +struct sockaddr_any +{ + union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + }; + + // The type is intended to be the same as the length + // parameter in ::accept, ::bind and ::connect functions. + + // This is the type used by SRT. + typedef int len_t; + + // This is the type used by system functions +#ifdef _WIN32 + typedef int syslen_t; +#else + typedef socklen_t syslen_t; +#endif + + // Note: by having `len_t` type here the usage in + // API functions is here limited to SRT. For system + // functions you can pass the address here as (socklen_t*)&sa.len, + // but just do it on your own risk, as there's no guarantee + // that sizes of `int` and `socklen_t` do not differ. The safest + // way seems to be using an intermediate proxy to be written + // back here from the value of `syslen_t`. + len_t len; + + struct SysLenWrapper + { + syslen_t syslen; + len_t& backwriter; + syslen_t* operator&() { return &syslen; } + + SysLenWrapper(len_t& source): syslen(source), backwriter(source) + { + } + + ~SysLenWrapper() + { + backwriter = syslen; + } + }; + + // Usage: + // ::accept(lsn_sock, sa.get(), &sa.syslen()); + SysLenWrapper syslen() + { + return SysLenWrapper(len); + } + + static size_t storage_size() + { + typedef union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + } ucopy; + return sizeof (ucopy); + } + + void reset() + { + // sin6 is the largest field + memset((&sin6), 0, sizeof sin6); + len = 0; + } + + // Default domain is unspecified, and + // in this case the size is 0. + // Note that AF_* (and alias PF_*) types have + // many various values, of which only + // AF_INET and AF_INET6 are handled here. + // Others make the same effect as unspecified. + explicit sockaddr_any(int domain = AF_UNSPEC) + { + // Default domain is "unspecified", 0 + reset(); + + // Overriding family as required in the parameters + // and the size then accordingly. + sa.sa_family = domain == AF_INET || domain == AF_INET6 ? domain : AF_UNSPEC; + switch (domain) + { + case AF_INET: + len = len_t(sizeof (sockaddr_in)); + break; + + // Use size of sin6 as the default size + // len must be properly set so that the + // family-less sockaddr is passed to bind/accept + default: + len = len_t(sizeof (sockaddr_in6)); + break; + } + } + + sockaddr_any(const sockaddr_storage& stor) + { + // Here the length isn't passed, so just rely on family. + set((const sockaddr*)&stor); + } + + sockaddr_any(const sockaddr* source, len_t namelen = 0) + { + if (namelen == 0) + set(source); + else + set(source, namelen); + } + + void set(const sockaddr* source) + { + // Less safe version, simply trust the caller that the + // memory at 'source' is also large enough to contain + // all data required for particular family. + if (source->sa_family == AF_INET) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6) + { + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + // Error fallback: no other families than IP are regarded. + // Note: socket set up this way isn't intended to be used + // for bind/accept. + sa.sa_family = AF_UNSPEC; + len = 0; + } + } + + void set(const sockaddr* source, syslen_t namelen) + { + // It's not safe to copy it directly, so check. + if (source->sa_family == AF_INET && namelen >= syslen_t(sizeof sin)) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6 && namelen >= syslen_t(sizeof sin6)) + { + // Note: this isn't too safe, may crash for stupid values + // of source->sa_family or any other data + // in the source structure, so make sure it's correct first. + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + reset(); + } + } + + void set(const sockaddr_in& in4) + { + memcpy((&sin), &in4, sizeof in4); + len = sizeof in4; + } + + void set(const sockaddr_in6& in6) + { + memcpy((&sin6), &in6, sizeof in6); + len = sizeof in6; + } + + sockaddr_any(const in_addr& i4_adr, uint16_t port) + { + // Some cases require separately IPv4 address passed as in_addr, + // so port is given separately. + sa.sa_family = AF_INET; + sin.sin_addr = i4_adr; + sin.sin_port = htons(port); + len = sizeof sin; + } + + sockaddr_any(const in6_addr& i6_adr, uint16_t port) + { + sa.sa_family = AF_INET6; + sin6.sin6_addr = i6_adr; + sin6.sin6_port = htons(port); + len = sizeof sin6; + } + + static len_t size(int family) + { + switch (family) + { + case AF_INET: + return len_t(sizeof (sockaddr_in)); + + case AF_INET6: + return len_t(sizeof (sockaddr_in6)); + + default: + return 0; // fallback + } + } + + bool empty() const + { + bool isempty = true; // unspec-family address is always empty + + if (sa.sa_family == AF_INET) + { + isempty = (sin.sin_port == 0 + && sin.sin_addr.s_addr == 0); + } + else if (sa.sa_family == AF_INET6) + { + isempty = (sin6.sin6_port == 0 + && memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0); + } + // otherwise isempty stays with default false + return isempty; + } + + len_t size() const + { + return size(sa.sa_family); + } + + int family() const { return sa.sa_family; } + void family(int val) + { + sa.sa_family = val; + len = size(); + } + + // port is in exactly the same location in both sin and sin6 + // and has the same size. This is actually yet another common + // field, just not mentioned in the sockaddr structure. + uint16_t& r_port() { return sin.sin_port; } + uint16_t r_port() const { return sin.sin_port; } + int hport() const { return ntohs(sin.sin_port); } + + void hport(int value) + { + // Port is fortunately located at the same position + // in both sockaddr_in and sockaddr_in6 and has the + // same size. + sin.sin_port = htons(value); + } + + sockaddr* get() { return &sa; } + const sockaddr* get() const { return &sa; } + + // Sometimes you need to get the address + // the way suitable for e.g. inet_ntop. + const void* get_addr() const + { + if (sa.sa_family == AF_INET) + return &sin.sin_addr.s_addr; + + if (sa.sa_family == AF_INET6) + return &sin6.sin6_addr; + + return NULL; + } + + void* get_addr() + { + const sockaddr_any* that = this; + return (void*)that->get_addr(); + } + + template struct TypeMap; + + template + typename TypeMap::type& get(); + + struct Equal + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if (c1.family() != c2.family()) + return false; + + // Cannot use memcmp due to having in some systems + // another field like sockaddr_in::sin_len. This exists + // in some BSD-derived systems, but is not required by POSIX. + // Therefore sockaddr_any class cannot operate with it, + // as in this situation it would be safest to state that + // particular implementations may have additional fields + // of different purpose beside those required by POSIX. + // + // The only reliable way to compare two underlying sockaddr + // object is then to compare the port value and the address + // value. + // + // Fortunately the port is 16-bit and located at the same + // offset in both sockaddr_in and sockaddr_in6. + + return c1.sin.sin_port == c2.sin.sin_port + && c1.equal_address(c2); + } + }; + + struct EqualAddress + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if ( c1.sa.sa_family == AF_INET ) + { + return c1.sin.sin_addr.s_addr == c2.sin.sin_addr.s_addr; + } + + if ( c1.sa.sa_family == AF_INET6 ) + { + return memcmp(&c1.sin6.sin6_addr, &c2.sin6.sin6_addr, sizeof (in6_addr)) == 0; + } + + return false; + } + + }; + + bool equal_address(const sockaddr_any& rhs) const + { + return EqualAddress()(*this, rhs); + } + + struct Less + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + return memcmp(&c1, &c2, sizeof(c1)) < 0; + } + }; + + // Tests if the current address is the "any" wildcard. + bool isany() const + { + if (sa.sa_family == AF_INET) + return sin.sin_addr.s_addr == INADDR_ANY; + + if (sa.sa_family == AF_INET6) + return memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0; + + return false; + } + + // Debug support + std::string str() const + { + if (family() != AF_INET && family() != AF_INET6) + return "unknown:0"; + + std::ostringstream output; + char hostbuf[1024]; + int flags; + + #if ENABLE_GETNAMEINFO + flags = NI_NAMEREQD; + #else + flags = NI_NUMERICHOST | NI_NUMERICSERV; + #endif + + if (!getnameinfo(get(), size(), hostbuf, 1024, NULL, 0, flags)) + { + output << hostbuf; + } + + output << ":" << hport(); + return output.str(); + } + + bool operator==(const sockaddr_any& other) const + { + return Equal()(*this, other); + } + + bool operator!=(const sockaddr_any& other) const { return !(*this == other); } +}; + +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in type; }; +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in6 type; }; + +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin; } +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin6; } + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packet.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packet.h new file mode 100644 index 000000000..027d5f0b3 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packet.h @@ -0,0 +1,397 @@ +/* + * SRT - Secure Reliable Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/02/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_PACKET_H +#define INC_SRT_PACKET_H + +#include "udt.h" +#include "common.h" +#include "utilities.h" +#include "netinet_any.h" +#include "packetfilter_api.h" + +namespace srt +{ + +////////////////////////////////////////////////////////////////////////////// +// The purpose of the IOVector class is to proide a platform-independet interface +// to the WSABUF on Windows and iovec on Linux, that can be easilly converted +// to the native structure for use in WSARecvFrom() and recvmsg(...) functions +class IOVector +#ifdef _WIN32 + : public WSABUF +#else + : public iovec +#endif +{ +public: + inline void set(void* buffer, size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; + buf = (CHAR*)buffer; +#else + iov_base = (void*)buffer; + iov_len = length; +#endif + } + + inline char*& dataRef() + { +#ifdef _WIN32 + return buf; +#else + return (char*&)iov_base; +#endif + } + + inline char* data() + { +#ifdef _WIN32 + return buf; +#else + return (char*)iov_base; +#endif + } + + inline size_t size() const + { +#ifdef _WIN32 + return (size_t)len; +#else + return iov_len; +#endif + } + + inline void setLength(size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; +#else + iov_len = length; +#endif + } +}; + +/// To define packets in order in the buffer. This is public due to being used in buffer. +enum PacketBoundary +{ + PB_SUBSEQUENT = 0, // 00: a packet in the middle of a message, neither the first, not the last. + PB_LAST = 1, // 01: last packet of a message + PB_FIRST = 2, // 10: first packet of a message + PB_SOLO = 3, // 11: solo message packet +}; + +// Breakdown of the PM_SEQNO field in the header: +// C| X X ... X, where: +typedef Bits<31> SEQNO_CONTROL; +// 1|T T T T T T T T T T T T T T T|E E...E +typedef Bits<30, 16> SEQNO_MSGTYPE; +typedef Bits<15, 0> SEQNO_EXTTYPE; +// 0|S S ... S +typedef Bits<30, 0> SEQNO_VALUE; + +// This bit cannot be used by SEQNO anyway, so it's additionally used +// in LOSSREPORT data specification to define that this value is the +// BEGIN value for a SEQNO range (to distinguish it from a SOLO loss SEQNO value). +const int32_t LOSSDATA_SEQNO_RANGE_FIRST = SEQNO_CONTROL::mask; + +// Just cosmetics for readability. +const int32_t LOSSDATA_SEQNO_RANGE_LAST = 0, LOSSDATA_SEQNO_SOLO = 0; + +inline int32_t CreateControlSeqNo(UDTMessageType type) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(uint32_t(type)); +} + +inline int32_t CreateControlExtSeqNo(int exttype) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(size_t(UMSG_EXT)) | SEQNO_EXTTYPE::wrap(exttype); +} + +// MSGNO breakdown: B B|O|K K|R|M M M M M M M M M M...M +typedef Bits<31, 30> MSGNO_PACKET_BOUNDARY; +typedef Bits<29> MSGNO_PACKET_INORDER; +typedef Bits<28, 27> MSGNO_ENCKEYSPEC; +#if 1 // can block rexmit flag +// New bit breakdown - rexmit flag supported. +typedef Bits<26> MSGNO_REXMIT; +typedef Bits<25, 0> MSGNO_SEQ; +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ_OLD; +// This symbol is for older SRT version, where the peer does not support the MSGNO_REXMIT flag. +// The message should be extracted as PMASK_MSGNO_SEQ, if REXMIT is supported, and PMASK_MSGNO_SEQ_OLD otherwise. + +const uint32_t PACKET_SND_NORMAL = 0, PACKET_SND_REXMIT = MSGNO_REXMIT::mask; +const int MSGNO_SEQ_MAX = MSGNO_SEQ::mask; + +#else +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ; +#endif + +typedef RollNumber MsgNo; + +// constexpr in C++11 ! +inline int32_t PacketBoundaryBits(PacketBoundary o) +{ + return MSGNO_PACKET_BOUNDARY::wrap(int32_t(o)); +} + +enum EncryptionKeySpec +{ + EK_NOENC = 0, + EK_EVEN = 1, + EK_ODD = 2 +}; + +enum EncryptionStatus +{ + ENCS_CLEAR = 0, + ENCS_FAILED = -1, + ENCS_NOTSUP = -2 +}; + +const int32_t PMASK_MSGNO_ENCKEYSPEC = MSGNO_ENCKEYSPEC::mask; +inline int32_t EncryptionKeyBits(EncryptionKeySpec f) +{ + return MSGNO_ENCKEYSPEC::wrap(int32_t(f)); +} +inline EncryptionKeySpec GetEncryptionKeySpec(int32_t msgno) +{ + return EncryptionKeySpec(MSGNO_ENCKEYSPEC::unwrap(msgno)); +} + +const int32_t PUMASK_SEQNO_PROBE = 0xF; + +std::string PacketMessageFlagStr(uint32_t msgno_field); + +class CPacket +{ + friend class CChannel; + friend class CSndQueue; + friend class CRcvQueue; + +public: + CPacket(); + ~CPacket(); + + void allocate(size_t size); + void deallocate(); + + /// Get the payload or the control information field length. + /// @return the payload or the control information field length. + size_t getLength() const; + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + void setLength(size_t len); + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + /// @param cap [in] capacity (if known). + void setLength(size_t len, size_t cap); + + /// Pack a Control packet. + /// @param pkttype [in] packet type filed. + /// @param lparam [in] pointer to the first data structure, explained by the packet type. + /// @param rparam [in] pointer to the second data structure, explained by the packet type. + /// @param size [in] size of rparam, in number of bytes; + void pack(UDTMessageType pkttype, const int32_t* lparam = NULL, void* rparam = NULL, size_t size = 0); + + /// Read the packet vector. + /// @return Pointer to the packet vector. + IOVector* getPacketVector(); + + uint32_t* getHeader() { return m_nHeader; } + + /// Read the packet type. + /// @return packet type filed (000 ~ 111). + UDTMessageType getType() const; + + bool isControl(UDTMessageType type) const { return isControl() && type == getType(); } + + bool isControl() const { return 0 != SEQNO_CONTROL::unwrap(m_nHeader[SRT_PH_SEQNO]); } + + void setControl(UDTMessageType type) { m_nHeader[SRT_PH_SEQNO] = SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(type); } + + /// Read the extended packet type. + /// @return extended packet type filed (0x000 ~ 0xFFF). + int getExtendedType() const; + + /// Read the ACK-2 seq. no. + /// @return packet header field (bit 16~31). + int32_t getAckSeqNo() const; + + uint16_t getControlFlags() const; + + // Note: this will return a "singular" value, if the packet + // contains the control message + int32_t getSeqNo() const { return m_nHeader[SRT_PH_SEQNO]; } + + /// Read the message boundary flag bit. + /// @return packet header field [1] (bit 0~1). + PacketBoundary getMsgBoundary() const; + + /// Read the message inorder delivery flag bit. + /// @return packet header field [1] (bit 2). + bool getMsgOrderFlag() const; + + /// Read the rexmit flag (true if the packet was sent due to retransmission). + /// If the peer does not support retransmission flag, the current agent cannot use it as well + /// (because the peer will understand this bit as a part of MSGNO field). + bool getRexmitFlag() const; + + void setRexmitFlag(bool bRexmit); + + /// Read the message sequence number. + /// @return packet header field [1] + int32_t getMsgSeq(bool has_rexmit = true) const; + + /// Read the message crypto key bits. + /// @return packet header field [1] (bit 3~4). + EncryptionKeySpec getMsgCryptoFlags() const; + + void setMsgCryptoFlags(EncryptionKeySpec spec); + + /// Read the message time stamp. + /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). + uint32_t getMsgTimeStamp() const; + + sockaddr_any udpDestAddr() const { return m_DestAddr; } + +#ifdef SRT_DEBUG_TSBPD_WRAP // Receiver + static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; // 27 bit fast wraparound for tests (~2m15s) +#else + static const uint32_t MAX_TIMESTAMP = 0xFFFFFFFF; // Full 32 bit (01h11m35s) +#endif + +protected: + static const uint32_t TIMESTAMP_MASK = MAX_TIMESTAMP; // this value to be also used as a mask +public: + /// Clone this packet. + /// @return Pointer to the new packet. + CPacket* clone() const; + + enum PacketVectorFields + { + PV_HEADER = 0, + PV_DATA = 1, + + PV_SIZE = 2 + }; + +public: + void toNL(); + void toHL(); + +protected: + // DynamicStruct is the same as array of given type and size, just it + // enforces that you index it using a symbol from symbolic enum type, not by a bare integer. + typedef DynamicStruct HEADER_TYPE; + HEADER_TYPE m_nHeader; //< The 128-bit header field + + IOVector m_PacketVector[PV_SIZE]; //< The two-dimensional vector of an SRT packet [header, data] + + int32_t m_extra_pad; + bool m_data_owned; + sockaddr_any m_DestAddr; + size_t m_zCapacity; + +protected: + CPacket& operator=(const CPacket&); + CPacket(const CPacket&); + +public: + int32_t& m_iSeqNo; // alias: sequence number + int32_t& m_iMsgNo; // alias: message number + int32_t& m_iTimeStamp; // alias: timestamp + int32_t& m_iID; // alias: destination SRT socket ID + char*& m_pcData; // alias: payload (data packet) / control information fields (control packet) + + // Experimental: sometimes these references don't work! + char* getData(); + char* release(); + + static const size_t HDR_SIZE = sizeof(HEADER_TYPE); // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t) + + // Can also be calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr). + static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }. + + static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE; + + // Maximum transmission unit size. 1500 in case of Ethernet II (RFC 1191). + static const size_t ETH_MAX_MTU_SIZE = 1500; + + // Maximum payload size of an SRT packet. + static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE; + + // Packet interface + char* data() { return m_pcData; } + const char* data() const { return m_pcData; } + size_t size() const { return getLength(); } + size_t capacity() const { return m_zCapacity; } + void setCapacity(size_t cap) { m_zCapacity = cap; } + uint32_t header(SrtPktHeaderFields field) const { return m_nHeader[field]; } + +#if ENABLE_LOGGING + std::string MessageFlagStr() { return PacketMessageFlagStr(m_nHeader[SRT_PH_MSGNO]); } + std::string Info(); +#else + std::string MessageFlagStr() { return std::string(); } + std::string Info() { return std::string(); } +#endif +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter.h new file mode 100644 index 000000000..429e81e79 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter.h @@ -0,0 +1,219 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_H +#define INC_SRT_PACKETFILTER_H + +#include +#include +#include + +#include "packet.h" +#include "utilities.h" +#include "packetfilter_api.h" + +namespace srt { + +class CUnitQueue; +struct CUnit; +class CUDT; + +class PacketFilter +{ + friend class SrtPacketFilterBase; + +public: + typedef std::vector< std::pair > loss_seqs_t; + + typedef SrtPacketFilterBase* filter_create_t(const SrtFilterInitializer& init, std::vector&, const std::string& config); + + class Factory + { + public: + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, std::vector& provided, const std::string& confstr) = 0; + + // Characteristic data + virtual size_t ExtraSize() const = 0; + + // Represent default parameters. This is for completing and comparing + // filter configurations from both parties. Possible values to return: + // - an empty string (all parameters are mandatory) + // - a form of: ",:,..." + virtual std::string defaultConfig() const = 0; + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const = 0; + virtual ~Factory(); + }; +private: + friend bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + + template + class Creator: public Factory + { + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, + std::vector& provided, + const std::string& confstr) ATR_OVERRIDE + { return new Target(init, provided, confstr); } + + // Import the extra size data + virtual size_t ExtraSize() const ATR_OVERRIDE { return Target::EXTRA_SIZE; } + virtual std::string defaultConfig() const ATR_OVERRIDE { return Target::defaultConfig; } + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const ATR_OVERRIDE + { + return Target::verifyConfig(config, (w_errormsg)); + } + + public: + Creator() {} + virtual ~Creator() {} + }; + + + // We need a private wrapper for the auto-pointer, can't use + // std::unique_ptr here due to no C++11. + struct ManagedPtr + { + Factory* f; + mutable bool owns; + + // Accept whatever + ManagedPtr(Factory* ff): f(ff), owns(true) {} + ManagedPtr(): f(NULL), owns(false) {} + ~ManagedPtr() + { + if (owns) + delete f; + } + + void copy_internal(const ManagedPtr& other) + { + other.owns = false; + f = other.f; + owns = true; + } + + ManagedPtr(const ManagedPtr& other) + { + copy_internal(other); + } + + void operator=(const ManagedPtr& other) + { + if (owns) + delete f; + copy_internal(other); + } + + Factory* operator->() { return f; } + Factory* get() { return f; } + }; + + // The list of builtin names that are reserved. + static std::set builtin_filters; + + // Temporarily changed to linear searching, until this is exposed + // for a user-defined filter. + typedef std::map filters_map_t; + static filters_map_t filters; + + // This is a filter container. + SrtPacketFilterBase* m_filter; + void Check() + { +#if ENABLE_DEBUG + if (!m_filter) + abort(); +#endif + // Don't do any check for now. + } + +public: + + static void globalInit(); + + static bool IsBuiltin(const std::string&); + + template + static bool add(const std::string& name) + { + if (IsBuiltin(name)) + return false; + + filters[name] = new Creator; + return true; + } + + static Factory* find(const std::string& type) + { + filters_map_t::iterator i = filters.find(type); + if (i == filters.end()) + return NULL; // No matter what to return - this is "undefined behavior" to be prevented + return i->second.get(); + } + + // Filter is optional, so this check should be done always + // manually. + bool installed() const { return m_filter; } + operator bool() const { return installed(); } + + SrtPacketFilterBase* operator->() { Check(); return m_filter; } + + // In the beginning it's initialized as first, builtin default. + // Still, it will be created only when requested. + PacketFilter(): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // Copy constructor - important when listener-spawning + // Things being done: + // 1. The filter is individual, so don't copy it. Set NULL. + // 2. This will be configued anyway basing on possibly a new rule set. + PacketFilter(const PacketFilter& source SRT_ATR_UNUSED): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // This function will be called by the parent CUDT + // in appropriate time. It should select appropriate + // filter basing on the value in selector, then + // pin oneself in into CUDT for receiving event signals. + bool configure(CUDT* parent, CUnitQueue* uq, const std::string& confstr); + + static bool correctConfig(const SrtFilterConfig& c); + + // Will delete the pinned in filter object. + // This must be defined in *.cpp file due to virtual + // destruction. + ~PacketFilter(); + + // Simple wrappers + void feedSource(CPacket& w_packet); + SRT_ARQLevel arqLevel(); + bool packControlPacket(int32_t seq, int kflg, CPacket& w_packet); + void receive(CUnit* unit, std::vector& w_incoming, loss_seqs_t& w_loss_seqs); + +protected: + PacketFilter& operator=(const PacketFilter& p); + void InsertRebuilt(std::vector& incoming, CUnitQueue* uq); + + CUDT* m_parent; + + // Sender part + SrtPacket m_sndctlpkt; + + // Receiver part + CUnitQueue* m_unitq; + std::vector m_provided; +}; + +bool CheckFilterCompat(SrtFilterConfig& w_agent, SrtFilterConfig peer); + +inline void PacketFilter::feedSource(CPacket& w_packet) { SRT_ASSERT(m_filter); return m_filter->feedSource((w_packet)); } +inline SRT_ARQLevel PacketFilter::arqLevel() { SRT_ASSERT(m_filter); return m_filter->arqLevel(); } + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_api.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_api.h new file mode 100644 index 000000000..3bfba7c76 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_api.h @@ -0,0 +1,158 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_API_H +#define INC_SRT_PACKETFILTER_API_H + +#include "platform_sys.h" + +#include +#include +#include +#include +#include + +namespace srt { + +class CPacket; + +enum SrtPktHeaderFields +{ + SRT_PH_SEQNO = 0, //< sequence number + SRT_PH_MSGNO = 1, //< message number + SRT_PH_TIMESTAMP = 2, //< time stamp + SRT_PH_ID = 3, //< socket ID + + // Must be the last value - this is size of all, not a field id + SRT_PH_E_SIZE +}; + + +enum SRT_ARQLevel +{ + SRT_ARQ_NEVER, //< Never send LOSSREPORT + SRT_ARQ_ONREQ, //< Only record the loss, but report only those that are returned in receive() + SRT_ARQ_ALWAYS, //< always send LOSSREPORT immediately after detecting a loss +}; + +struct SrtConfig +{ + std::string type; + typedef std::map par_t; + par_t parameters; +}; + +struct SrtFilterConfig: SrtConfig +{ + size_t extra_size; // needed for filter option check against payload size +}; + +struct SrtFilterInitializer +{ + SRTSOCKET socket_id; + int32_t snd_isn; + int32_t rcv_isn; + size_t payload_size; + size_t rcvbuf_size; +}; + +struct SrtPacket +{ + uint32_t hdr[SRT_PH_E_SIZE]; + char buffer[SRT_LIVE_MAX_PLSIZE]; + size_t length; + + SrtPacket(size_t size): length(size) + { + memset(hdr, 0, sizeof(hdr)); + } + + uint32_t header(SrtPktHeaderFields field) { return hdr[field]; } + char* data() { return buffer; } + const char* data() const { return buffer; } + size_t size() const { return length; } +}; + + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& w_config); + + +class SrtPacketFilterBase +{ + SrtFilterInitializer initParams; + +protected: + + SRTSOCKET socketID() const { return initParams.socket_id; } + int32_t sndISN() const { return initParams.snd_isn; } + int32_t rcvISN() const { return initParams.rcv_isn; } + size_t payloadSize() const { return initParams.payload_size; } + size_t rcvBufferSize() const { return initParams.rcvbuf_size; } + + friend class PacketFilter; + + // Beside the size of the rows, special values: + // 0: if you have 0 specified for rows, there are only columns + // -1: Only during the handshake, use the value specified by peer. + // -N: The N value still specifies the size, but in particular + // dimension there is no filter control packet formed nor expected. + +public: + + typedef std::vector< std::pair > loss_seqs_t; + +protected: + + SrtPacketFilterBase(const SrtFilterInitializer& i): initParams(i) + { + } + + // Sender side + + /// This function creates and stores the filter control packet with + /// a prediction to be immediately sent. This is called in the function + /// that normally is prepared for extracting a data packet from the sender + /// buffer and send it over the channel. The returned value informs the + /// caller whether the control packet was available and therefore provided. + /// @param [OUT] packet Target place where the packet should be stored + /// @param [IN] seq Sequence number of the packet last requested for sending + /// @return true if the control packet has been provided + virtual bool packControlPacket(SrtPacket& packet, int32_t seq) = 0; + + /// This is called at the moment when the sender queue decided to pick up + /// a new packet from the scheduled packets. This should be then used to + /// continue filling the group, possibly followed by final calculating the + /// control packet ready to send. The packet received by this function is + /// potentially allowed to be modified. + /// @param [INOUT] packet The packet about to send + virtual void feedSource(CPacket& packet) = 0; + + + // Receiver side + + // This function is called at the moment when a new data packet has + // arrived (no matter if subsequent or recovered). The 'state' value + // defines the configured level of loss state required to send the + // loss report. + virtual bool receive(const CPacket& pkt, loss_seqs_t& loss_seqs) = 0; + + // Backward configuration. + // This should have some stable value after the configuration is parsed, + // and it should be a stable value set ONCE, after the filter module is ready. + virtual SRT_ARQLevel arqLevel() = 0; + + virtual ~SrtPacketFilterBase() + { + } +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_builtin.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_builtin.h new file mode 100644 index 000000000..80983250a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/packetfilter_builtin.h @@ -0,0 +1,18 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +#ifndef INC_SRT_PACKETFILTER_BUILTIN_H +#define INC_SRT_PACKETFILTER_BUILTIN_H + +// Integration header +#include "fec.h" + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/platform_sys.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/platform_sys.h index fae95803f..e2f0aa4d9 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/platform_sys.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/platform_sys.h @@ -7,28 +7,113 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ -#ifndef INC__PLATFORM_SYS_H -#define INC__PLATFORM_SYS_H +#ifndef INC_SRT_PLATFORM_SYS_H +#define INC_SRT_PLATFORM_SYS_H + +// INFORMATION +// +// This file collects all required platform-specific declarations +// required to provide everything that the SRT library needs from system. +// +// There's also semi-modular system implemented using SRT_IMPORT_* macros. +// To require a module to be imported, #define SRT_IMPORT_* where * is +// the module name. Currently handled module macros: +// +// SRT_IMPORT_TIME (mach time on Mac, portability gettimeofday on WIN32) +// SRT_IMPORT_EVENT (includes kevent on Mac) + #ifdef _WIN32 #include #include #include #include + +#ifndef __MINGW32__ + #include +#endif + + #ifdef SRT_IMPORT_TIME + #include + #endif + #include #include - #if defined(_MSC_VER) - #pragma warning(disable:4251) - #endif #else + +#if defined(__APPLE__) && __APPLE__ +// Warning: please keep this test as it is, do not make it +// "#if __APPLE__" or "#ifdef __APPLE__". In applications with +// a strict "no warning policy", "#if __APPLE__" triggers an "undef" +// error. With GCC, an old & never fixed bug prevents muting this +// warning (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431). +// Before this fix, the solution was to "#define __APPLE__ 0" before +// including srt.h. So, don't use "#ifdef __APPLE__" either. + +// XXX Check if this condition doesn't require checking of +// also other macros, like TARGET_OS_IOS etc. + +#include "TargetConditionals.h" +#define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ + +#ifdef SRT_IMPORT_TIME + #include +#endif + +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif + +#endif + +#ifdef BSD +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif +#endif + +#ifdef LINUX + +#ifdef SRT_IMPORT_EVENT + #include + #include +#endif + +#endif + +#ifdef __ANDROID__ + +#ifdef SRT_IMPORT_EVENT + #include +#endif + +#endif + #include #include +#include #include #include #include #include #include -#include +#include + +#ifdef __cplusplus +// Headers for errno, string and stdlib are +// included indirectly correct C++ way. +#else +#include +#include +#include +#endif + #endif #endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/queue.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/queue.h new file mode 100644 index 000000000..dd68a7721 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/queue.h @@ -0,0 +1,603 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/12/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_QUEUE_H +#define INC_SRT_QUEUE_H + +#include "common.h" +#include "packet.h" +#include "socketconfig.h" +#include "netinet_any.h" +#include "utilities.h" +#include +#include +#include +#include + +namespace srt +{ +class CChannel; +class CUDT; + +struct CUnit +{ + CPacket m_Packet; // packet + sync::atomic m_bTaken; // true if the unit is is use (can be stored in the RCV buffer). +}; + +class CUnitQueue +{ +public: + /// @brief Construct a unit queue. + /// @param mss Initial number of units to allocate. + /// @param mss Maximum segment size meaning the size of each unit. + /// @throws CUDTException SRT_ENOBUF. + CUnitQueue(int initNumUnits, int mss); + ~CUnitQueue(); + +public: + int capacity() const { return m_iSize; } + int size() const { return m_iSize - m_iNumTaken; } + +public: + /// @brief Find an available unit for incoming packet. Allocate new units if 90% or more are in use. + /// @note This function is not thread-safe. Currently only CRcvQueue::worker thread calls it, thus + /// it is not an issue. However, must be protected if used from several threads in the future. + /// @return Pointer to the available unit, NULL if not found. + CUnit* getNextAvailUnit(); + + void makeUnitFree(CUnit* unit); + + void makeUnitTaken(CUnit* unit); + +private: + struct CQEntry + { + CUnit* m_pUnit; // unit queue + char* m_pBuffer; // data buffer + int m_iSize; // size of each queue + + CQEntry* m_pNext; + }; + + /// Increase the unit queue size (by @a m_iBlockSize units). + /// Uses m_mtx to protect access and changes of the queue state. + /// @return 0: success, -1: failure. + int increase_(); + + /// @brief Allocated a CQEntry of iNumUnits with each unit of mss bytes. + /// @param iNumUnits a number of units to allocate + /// @param mss the size of each unit in bytes. + /// @return a pointer to a newly allocated entry on success, NULL otherwise. + static CQEntry* allocateEntry(const int iNumUnits, const int mss); + +private: + CQEntry* m_pQEntry; // pointer to the first unit queue + CQEntry* m_pCurrQueue; // pointer to the current available queue + CQEntry* m_pLastQueue; // pointer to the last unit queue + CUnit* m_pAvailUnit; // recent available unit + int m_iSize; // total size of the unit queue, in number of packets + sync::atomic m_iNumTaken; // total number of valid (occupied) packets in the queue + const int m_iMSS; // unit buffer size + const int m_iBlockSize; // Number of units in each CQEntry. + +private: + CUnitQueue(const CUnitQueue&); + CUnitQueue& operator=(const CUnitQueue&); +}; + +struct CSNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; + + sync::atomic m_iHeapLoc; // location on the heap, -1 means not on the heap +}; + +class CSndUList +{ +public: + CSndUList(sync::CTimer* pTimer); + ~CSndUList(); + +public: + enum EReschedule + { + DONT_RESCHEDULE = 0, + DO_RESCHEDULE = 1 + }; + + static EReschedule rescheduleIf(bool cond) { return cond ? DO_RESCHEDULE : DONT_RESCHEDULE; } + + /// Update the timestamp of the UDT instance on the list. + /// @param [in] u pointer to the UDT instance + /// @param [in] reschedule if the timestamp should be rescheduled + /// @param [in] ts the next time to trigger sending logic on the CUDT + void update(const CUDT* u, EReschedule reschedule, sync::steady_clock::time_point ts = sync::steady_clock::now()); + + /// Retrieve the next (in time) socket from the heap to process its sending request. + /// @return a pointer to CUDT instance to process next. + CUDT* pop(); + + /// Remove UDT instance from the list. + /// @param [in] u pointer to the UDT instance + void remove(const CUDT* u);// EXCLUDES(m_ListLock); + + /// Retrieve the next scheduled processing time. + /// @return Scheduled processing time of the first UDT socket in the list. + sync::steady_clock::time_point getNextProcTime(); + + /// Wait for the list to become non empty. + void waitNonEmpty() const; + + /// Signal to stop waiting in waitNonEmpty(). + void signalInterrupt() const; + +private: + /// Doubles the size of the list. + /// + void realloc_();// REQUIRES(m_ListLock); + + /// Insert a new UDT instance into the list with realloc if required. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_(const sync::steady_clock::time_point& ts, const CUDT* u); + + /// Insert a new UDT instance into the list without realloc. + /// Should be called if there is a guaranteed space for the element. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_norealloc_(const sync::steady_clock::time_point& ts, const CUDT* u);// REQUIRES(m_ListLock); + + /// Removes CUDT entry from the list. + /// If the last entry is removed, calls sync::CTimer::interrupt(). + void remove_(const CUDT* u); + +private: + CSNode** m_pHeap; // The heap array + int m_iArrayLength; // physical length of the array + int m_iLastEntry; // position of last entry on the heap array or -1 if empty. + + mutable sync::Mutex m_ListLock; // Protects the list (m_pHeap, m_iArrayLength, m_iLastEntry). + mutable sync::Condition m_ListCond; + + sync::CTimer* const m_pTimer; + +private: + CSndUList(const CSndUList&); + CSndUList& operator=(const CSndUList&); +}; + +struct CRNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; // Time Stamp + + CRNode* m_pPrev; // previous link + CRNode* m_pNext; // next link + + sync::atomic m_bOnList; // if the node is already on the list +}; + +class CRcvUList +{ +public: + CRcvUList(); + ~CRcvUList(); + +public: + /// Insert a new UDT instance to the list. + /// @param [in] u pointer to the UDT instance + + void insert(const CUDT* u); + + /// Remove the UDT instance from the list. + /// @param [in] u pointer to the UDT instance + + void remove(const CUDT* u); + + /// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing. + /// @param [in] u pointer to the UDT instance + + void update(const CUDT* u); + +public: + CRNode* m_pUList; // the head node + +private: + CRNode* m_pLast; // the last node + +private: + CRcvUList(const CRcvUList&); + CRcvUList& operator=(const CRcvUList&); +}; + +class CHash +{ +public: + CHash(); + ~CHash(); + +public: + /// Initialize the hash table. + /// @param [in] size hash table size + + void init(int size); + + /// Look for a UDT instance from the hash table. + /// @param [in] id socket ID + /// @return Pointer to a UDT instance, or NULL if not found. + + CUDT* lookup(int32_t id); + + /// Insert an entry to the hash table. + /// @param [in] id socket ID + /// @param [in] u pointer to the UDT instance + + void insert(int32_t id, CUDT* u); + + /// Remove an entry from the hash table. + /// @param [in] id socket ID + + void remove(int32_t id); + +private: + struct CBucket + { + int32_t m_iID; // Socket ID + CUDT* m_pUDT; // Socket instance + + CBucket* m_pNext; // next bucket + } * *m_pBucket; // list of buckets (the hash table) + + int m_iHashSize; // size of hash table + +private: + CHash(const CHash&); + CHash& operator=(const CHash&); +}; + +/// @brief A queue of sockets pending for connection. +/// It can be either a caller socket in a non-blocking mode +/// (the connection has to be handled in background), +/// or a socket in rendezvous connection mode. +class CRendezvousQueue +{ +public: + CRendezvousQueue(); + ~CRendezvousQueue(); + +public: + /// @brief Insert a new socket pending for connection (non-blocking caller or rendezvous). + /// @param id socket ID. + /// @param u pointer to a corresponding CUDT instance. + /// @param addr remote address to connect to. + /// @param ttl timepoint for connection attempt to expire. + void insert(const SRTSOCKET& id, CUDT* u, const sockaddr_any& addr, const srt::sync::steady_clock::time_point& ttl); + + /// @brief Remove a socket from the connection pending list. + /// @param id socket ID. + void remove(const SRTSOCKET& id); + + /// @brief Locate a socket in the connection pending queue. + /// @param addr source address of the packet received over UDP (peer address). + /// @param id socket ID. + /// @return a pointer to CUDT instance retrieved, or NULL if nothing was found. + CUDT* retrieve(const sockaddr_any& addr, SRTSOCKET& id) const; + + /// @brief Update status of connections in the pending queue. + /// Stop connecting if TTL expires. Resend handshake request every 250 ms if no response from the peer. + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param pktIn packet received from the UDP socket. + void updateConnStatus(EReadStatus rst, EConnectStatus cst, CUnit* unit); + +private: + struct LinkStatusInfo + { + CUDT* u; + SRTSOCKET id; + int errorcode; + sockaddr_any peeraddr; + int token; + + struct HasID + { + SRTSOCKET id; + HasID(SRTSOCKET p) + : id(p) + { + } + bool operator()(const LinkStatusInfo& i) { return i.id == id; } + }; + }; + + /// @brief Qualify pending connections: + /// - Sockets with expired TTL go to the 'to_remove' list and removed from the queue straight away. + /// - If HS request is to be resent (resend 250 ms if no response from the peer) go to the 'to_process' list. + /// + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param iDstSockID destination socket ID of the received packet. + /// @param[in,out] toRemove stores sockets with expired TTL. + /// @param[in,out] toProcess stores sockets which should repeat (resend) HS connection request. + bool qualifyToHandle(EReadStatus rst, + EConnectStatus cst, + int iDstSockID, + std::vector& toRemove, + std::vector& toProcess); + +private: + struct CRL + { + SRTSOCKET m_iID; // SRT socket ID (self) + CUDT* m_pUDT; // CUDT instance + sockaddr_any m_PeerAddr; // SRT sonnection peer address + sync::steady_clock::time_point m_tsTTL; // the time that this request expires + }; + std::list m_lRendezvousID; // The sockets currently in rendezvous mode + + mutable sync::Mutex m_RIDListLock; +}; + +class CSndQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CSndQueue(); + ~CSndQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the sending queue. + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t Timer + void init(CChannel* c, sync::CTimer* t); + + /// Send out a packet to a given address. The @a src parameter is + /// blindly passed by the caller down the call with intention to + /// be received eventually by CChannel::sendto, and used only if + /// appropriate conditions state so. + /// @param [in] addr destination address + /// @param [in,ref] packet packet to be sent out + /// @param [in] src The source IP address (details above) + /// @return Size of data sent out. + int sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& src); + + /// Get the IP TTL. + /// @param [in] ttl IP Time To Live. + /// @return TTL. + int getIpTTL() const; + + /// Get the IP Type of Service. + /// @return ToS. + int getIpToS() const; + +#ifdef SRT_ENABLE_BINDTODEVICE + bool getBind(char* dst, size_t len) const; +#endif + + int ioctlQuery(int type) const; + int sockoptQuery(int level, int type) const; + + void setClosing() { m_bClosing = true; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + +private: + CSndUList* m_pSndUList; // List of UDT instances for data sending + CChannel* m_pChannel; // The UDP channel for data sending + sync::CTimer* m_pTimer; // Timing facility + + sync::atomic m_bClosing; // closing the worker + +public: +#if defined(SRT_DEBUG_SNDQ_HIGHRATE) //>>debug high freq worker + sync::steady_clock::duration m_DbgPeriod; + mutable sync::steady_clock::time_point m_DbgTime; + struct + { + unsigned long lIteration; // + unsigned long lSleepTo; // SleepTo + unsigned long lNotReadyPop; // Continue + unsigned long lSendTo; + unsigned long lNotReadyTs; + unsigned long lCondWait; // block on m_WindowCond + } mutable m_WorkerStats; +#endif /* SRT_DEBUG_SNDQ_HIGHRATE */ + +private: + +#if ENABLE_LOGGING + static int m_counter; +#endif + + CSndQueue(const CSndQueue&); + CSndQueue& operator=(const CSndQueue&); +}; + +class CRcvQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CRcvQueue(); + ~CRcvQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the receiving queue. + /// @param [in] size queue size + /// @param [in] mss maximum packet size + /// @param [in] version IP version + /// @param [in] hsize hash table size + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t timer + void init(int size, size_t payload, int version, int hsize, CChannel* c, sync::CTimer* t); + + /// Read a packet for a specific UDT socket id. + /// @param [in] id Socket ID + /// @param [out] packet received packet + /// @return Data size of the packet + int recvfrom(int32_t id, CPacket& to_packet); + + void stopWorker(); + + void setClosing() { m_bClosing = true; } + + int getIPversion() { return m_iIPversion; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + // Subroutines of worker + EReadStatus worker_RetrieveUnit(int32_t& id, CUnit*& unit, sockaddr_any& sa); + EConnectStatus worker_ProcessConnectionRequest(CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_TryAsyncRend_OrStore(int32_t id, CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr_any& sa); + +private: + CUnitQueue* m_pUnitQueue; // The received packet queue + CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue + CHash* m_pHash; // Hash table for UDT socket looking up + CChannel* m_pChannel; // UDP channel for receiving packets + sync::CTimer* m_pTimer; // shared timer with the snd queue + + int m_iIPversion; // IP version + size_t m_szPayloadSize; // packet payload size + + sync::atomic m_bClosing; // closing the worker +#if ENABLE_LOGGING + static srt::sync::atomic m_counter; // A static counter to log RcvQueue worker thread number. +#endif + +private: + int setListener(CUDT* u); + void removeListener(const CUDT* u); + + void registerConnector(const SRTSOCKET& id, + CUDT* u, + const sockaddr_any& addr, + const sync::steady_clock::time_point& ttl); + void removeConnector(const SRTSOCKET& id); + + void setNewEntry(CUDT* u); + bool ifNewEntry(); + CUDT* getNewEntry(); + + void storePktClone(int32_t id, const CPacket& pkt); + +private: + sync::Mutex m_LSLock; + CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity + CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode + + std::vector m_vNewEntry; // newly added entries, to be inserted + sync::Mutex m_IDLock; + + std::map > m_mBuffer; // temporary buffer for rendezvous connection request + sync::Mutex m_BufferLock; + sync::Condition m_BufferCond; + +private: + CRcvQueue(const CRcvQueue&); + CRcvQueue& operator=(const CRcvQueue&); +}; + +struct CMultiplexer +{ + CSndQueue* m_pSndQueue; // The sending queue + CRcvQueue* m_pRcvQueue; // The receiving queue + CChannel* m_pChannel; // The UDP channel for sending and receiving + sync::CTimer* m_pTimer; // The timer + + int m_iPort; // The UDP port number of this multiplexer + int m_iIPversion; // Address family (AF_INET or AF_INET6) + int m_iRefCount; // number of UDT instances that are associated with this multiplexer + + CSrtMuxerConfig m_mcfg; + + int m_iID; // multiplexer ID + + // Constructor should reset all pointers to NULL + // to prevent dangling pointer when checking for memory alloc fails + CMultiplexer() + : m_pSndQueue(NULL) + , m_pRcvQueue(NULL) + , m_pChannel(NULL) + , m_pTimer(NULL) + { + } + + void destroy(); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/socketconfig.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/socketconfig.h new file mode 100644 index 000000000..403616edf --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/socketconfig.h @@ -0,0 +1,410 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_SOCKETCONFIG_H +#define INC_SRT_SOCKETCONFIG_H + +#include "platform_sys.h" +#ifdef SRT_ENABLE_BINDTODEVICE +#include +#endif +#include +#include "haicrypt.h" +#include "congctl.h" +#include "packet.h" +#include "handshake.h" +#include "logger_defs.h" +#include "packetfilter.h" + +// SRT Version constants +#define SRT_VERSION_UNK 0 +#define SRT_VERSION_MAJ1 0x010000 /* Version 1 major */ +#define SRT_VERSION_MAJ(v) (0xFF0000 & (v)) /* Major number ensuring backward compatibility */ +#define SRT_VERSION_MIN(v) (0x00FF00 & (v)) +#define SRT_VERSION_PCH(v) (0x0000FF & (v)) + +// NOTE: SRT_VERSION is primarily defined in the build file. +extern const int32_t SRT_DEF_VERSION; + +namespace srt +{ + +struct CSrtMuxerConfig +{ + static const int DEF_UDP_BUFFER_SIZE = 65536; + + int iIpTTL; + int iIpToS; + int iIpV6Only; // IPV6_V6ONLY option (-1 if not set) + bool bReuseAddr; // reuse an exiting port or not, for UDP multiplexer + +#ifdef SRT_ENABLE_BINDTODEVICE + std::string sBindToDevice; +#endif + int iUDPSndBufSize; // UDP sending buffer size + int iUDPRcvBufSize; // UDP receiving buffer size + + // NOTE: this operator is not reversable. The syntax must use: + // muxer_entry == socket_entry + bool isCompatWith(const CSrtMuxerConfig& other) const + { +#define CEQUAL(field) (field == other.field) + return CEQUAL(iIpTTL) + && CEQUAL(iIpToS) + && CEQUAL(bReuseAddr) +#ifdef SRT_ENABLE_BINDTODEVICE + && CEQUAL(sBindToDevice) +#endif + && CEQUAL(iUDPSndBufSize) + && CEQUAL(iUDPRcvBufSize) + && (other.iIpV6Only == -1 || CEQUAL(iIpV6Only)) + // NOTE: iIpV6Only is not regarded because + // this matches only in case of IPv6 with "any" address. + // And this aspect must be checked separately because here + // this procedure has no access to neither the address, + // nor the IP version (family). +#undef CEQUAL + && true; + } + + CSrtMuxerConfig() + : iIpTTL(-1) /* IPv4 TTL or IPv6 HOPs [1..255] (-1:undefined) */ + , iIpToS(-1) /* IPv4 Type of Service or IPv6 Traffic Class [0x00..0xff] (-1:undefined) */ + , iIpV6Only(-1) + , bReuseAddr(true) // This is default in SRT + , iUDPSndBufSize(DEF_UDP_BUFFER_SIZE) + , iUDPRcvBufSize(DEF_UDP_BUFFER_SIZE) + { + } +}; + +struct CSrtConfig; + +template +class StringStorage +{ + char stor[SIZE + 1]; + uint16_t len; + + // NOTE: default copying allowed. + +public: + StringStorage() + : len(0) + { + memset(stor, 0, sizeof stor); + } + + bool set(const char* s, size_t length) + { + if (length > SIZE) + return false; + + memcpy(stor, s, length); + stor[length] = 0; + len = (int) length; + return true; + } + + bool set(const std::string& s) + { + return set(s.c_str(), s.size()); + } + + size_t copy(char* s, size_t length) const + { + if (!s) + return 0; + + size_t copy_len = std::min((size_t)len, length); + memcpy(s, stor, copy_len); + return copy_len; + } + + std::string str() const + { + return len == 0 ? std::string() : std::string(stor); + } + + const char* c_str() const + { + return stor; + } + + size_t size() const { return size_t(len); } + bool empty() const { return len == 0; } +}; + +struct CSrtConfig: CSrtMuxerConfig +{ + typedef srt::sync::steady_clock::time_point time_point; + typedef srt::sync::steady_clock::duration duration; + + static const int + DEF_MSS = 1500, + DEF_FLIGHT_SIZE = 25600, + DEF_BUFFER_SIZE = 8192, //Rcv buffer MUST NOT be bigger than Flight Flag size + DEF_LINGER_S = 3*60, // 3 minutes + DEF_CONNTIMEO_S = 3; // 3 seconds + + enum + { + CIPHER_MODE_AUTO = 0, + CIPHER_MODE_AES_CTR = 1, + CIPHER_MODE_AES_GCM = 2 + }; + + static const int COMM_RESPONSE_TIMEOUT_MS = 5 * 1000; // 5 seconds + static const uint32_t COMM_DEF_MIN_STABILITY_TIMEOUT_MS = 60; // 60 ms + + // Mimimum recv flight flag size is 32 packets + static const int DEF_MIN_FLIGHT_PKT = 32; + static const size_t MAX_SID_LENGTH = 512; + static const size_t MAX_PFILTER_LENGTH = 64; + static const size_t MAX_CONG_LENGTH = 16; + + int iMSS; // Maximum Segment Size, in bytes + size_t zExpPayloadSize; // Expected average payload size (user option) + + // Options + bool bSynSending; // Sending synchronization mode + bool bSynRecving; // Receiving synchronization mode + int iFlightFlagSize; // Maximum number of packets in flight from the peer side + int iSndBufSize; // Maximum UDT sender buffer size + int iRcvBufSize; // Maximum UDT receiver buffer size + linger Linger; // Linger information on close + bool bRendezvous; // Rendezvous connection mode + + duration tdConnTimeOut; // connect timeout in milliseconds + bool bDriftTracer; + int iSndTimeOut; // sending timeout in milliseconds + int iRcvTimeOut; // receiving timeout in milliseconds + int64_t llMaxBW; // maximum data transfer rate (threshold) +#ifdef ENABLE_MAXREXMITBW + int64_t llMaxRexmitBW; // maximum bandwidth limit for retransmissions (Bytes/s). +#endif + + // These fields keep the options for encryption + // (SRTO_PASSPHRASE, SRTO_PBKEYLEN). Crypto object is + // created later and takes values from these. + HaiCrypt_Secret CryptoSecret; + int iSndCryptoKeyLen; + + // XXX Consider removing. The bDataSender stays here + // in order to maintain the HS side selection in HSv4. + bool bDataSender; + + bool bMessageAPI; + bool bTSBPD; // Whether AGENT will do TSBPD Rx (whether peer does, is not agent's problem) + int iRcvLatency; // Agent's Rx latency + int iPeerLatency; // Peer's Rx latency for the traffic made by Agent's Tx. + bool bTLPktDrop; // Whether Agent WILL DO TLPKTDROP on Rx. + int iSndDropDelay; // Extra delay when deciding to snd-drop for TLPKTDROP, -1 to off + bool bEnforcedEnc; // Off by default. When on, any connection other than nopw-nopw & pw1-pw1 is rejected. + int iGroupConnect; // 1 - allow group connections + int iPeerIdleTimeout_ms; // Timeout for hearing anything from the peer (ms). + uint32_t uMinStabilityTimeout_ms; + int iRetransmitAlgo; + int iCryptoMode; // SRTO_CRYPTOMODE + + int64_t llInputBW; // Input stream rate (bytes/sec). 0: use internally estimated input bandwidth + int64_t llMinInputBW; // Minimum input stream rate estimate (bytes/sec) + int iOverheadBW; // Percent above input stream rate (applies if llMaxBW == 0) + bool bRcvNakReport; // Enable Receiver Periodic NAK Reports + int iMaxReorderTolerance; //< Maximum allowed value for dynamic reorder tolerance + + // For the use of CCryptoControl + // HaiCrypt configuration + unsigned int uKmRefreshRatePkt; + unsigned int uKmPreAnnouncePkt; + + uint32_t uSrtVersion; + uint32_t uMinimumPeerSrtVersion; + + StringStorage sCongestion; + StringStorage sPacketFilterConfig; + StringStorage sStreamName; + + // Shortcuts and utilities + int32_t flightCapacity() + { + return std::min(iRcvBufSize, iFlightFlagSize); + } + + CSrtConfig() + : iMSS(DEF_MSS) + , zExpPayloadSize(SRT_LIVE_DEF_PLSIZE) + , bSynSending(true) + , bSynRecving(true) + , iFlightFlagSize(DEF_FLIGHT_SIZE) + , iSndBufSize(DEF_BUFFER_SIZE) + , iRcvBufSize(DEF_BUFFER_SIZE) + , bRendezvous(false) + , tdConnTimeOut(srt::sync::seconds_from(DEF_CONNTIMEO_S)) + , bDriftTracer(true) + , iSndTimeOut(-1) + , iRcvTimeOut(-1) + , llMaxBW(-1) +#ifdef ENABLE_MAXREXMITBW + , llMaxRexmitBW(-1) +#endif + , bDataSender(false) + , bMessageAPI(true) + , bTSBPD(true) + , iRcvLatency(SRT_LIVE_DEF_LATENCY_MS) + , iPeerLatency(0) + , bTLPktDrop(true) + , iSndDropDelay(0) + , bEnforcedEnc(true) + , iGroupConnect(0) + , iPeerIdleTimeout_ms(COMM_RESPONSE_TIMEOUT_MS) + , uMinStabilityTimeout_ms(COMM_DEF_MIN_STABILITY_TIMEOUT_MS) + , iRetransmitAlgo(1) + , iCryptoMode(CIPHER_MODE_AUTO) + , llInputBW(0) + , llMinInputBW(0) + , iOverheadBW(25) + , bRcvNakReport(true) + , iMaxReorderTolerance(0) // Sensible optimal value is 10, 0 preserves old behavior + , uKmRefreshRatePkt(0) + , uKmPreAnnouncePkt(0) + , uSrtVersion(SRT_DEF_VERSION) + , uMinimumPeerSrtVersion(SRT_VERSION_MAJ1) + + { + // Default UDT configurations + iUDPRcvBufSize = iRcvBufSize * iMSS; + + // Linger: LIVE mode defaults, please refer to `SRTO_TRANSTYPE` option + // for other modes. + Linger.l_onoff = 0; + Linger.l_linger = 0; + CryptoSecret.len = 0; + iSndCryptoKeyLen = 0; + + // Default congestion is "live". + // Available builtin congestions: "file". + // Others can be registerred. + sCongestion.set("live", 4); + } + + ~CSrtConfig() + { + // Wipeout critical data + memset(&CryptoSecret, 0, sizeof(CryptoSecret)); + } + + int set(SRT_SOCKOPT optName, const void* val, int size); +}; + +template +inline T cast_optval(const void* optval) +{ + return *reinterpret_cast(optval); +} + +template +inline T cast_optval(const void* optval, int optlen) +{ + if (optlen > 0 && optlen != sizeof(T)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + + return cast_optval(optval); +} + +// This function is to make it possible for both C and C++ +// API to accept both bool and int types for boolean options. +// (it's not that C couldn't use , it's that people +// often forget to use correct type). +template <> +inline bool cast_optval(const void* optval, int optlen) +{ + if (optlen == sizeof(bool)) + { + return *reinterpret_cast(optval); + } + + if (optlen == sizeof(int)) + { + // 0!= is a windows warning-killer int-to-bool conversion + return 0 != *reinterpret_cast(optval); + } + return false; +} + +} // namespace srt + +struct SRT_SocketOptionObject +{ + struct SingleOption + { + uint16_t option; + uint16_t length; + unsigned char storage[1]; // NOTE: Variable length object! + }; + + std::vector options; + + SRT_SocketOptionObject() {} + + ~SRT_SocketOptionObject() + { + for (size_t i = 0; i < options.size(); ++i) + { + // Convert back + unsigned char* mem = reinterpret_cast(options[i]); + delete[] mem; + } + } + + bool add(SRT_SOCKOPT optname, const void* optval, size_t optlen); +}; + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt.h index 0e566e859..53b6fd274 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt.h @@ -13,8 +13,8 @@ written by Haivision Systems Inc. *****************************************************************************/ -#ifndef INC__SRTC_H -#define INC__SRTC_H +#ifndef INC_SRTC_H +#define INC_SRTC_H #include "version.h" @@ -23,7 +23,6 @@ written by #include #include -#include "srt4udt.h" #include "logging_api.h" //////////////////////////////////////////////////////////////////////////////// @@ -36,7 +35,7 @@ written by #ifdef _WIN32 - #ifndef __MINGW__ + #ifndef __MINGW32__ // Explicitly define 32-bit and 64-bit numbers typedef __int32 int32_t; typedef __int64 int64_t; @@ -47,17 +46,14 @@ written by // VC 6.0 does not support unsigned __int64: may cause potential problems. typedef __int64 uint64_t; #endif - - #ifdef SRT_DYNAMIC - #ifdef SRT_EXPORTS - #define SRT_API __declspec(dllexport) - #else - #define SRT_API __declspec(dllimport) - #endif + #endif + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) #else - #define SRT_API + #define SRT_API __declspec(dllimport) #endif - #else // __MINGW__ + #else // !SRT_DYNAMIC #define SRT_API #endif #else @@ -69,48 +65,99 @@ written by // You can use these constants with SRTO_MINVERSION option. #define SRT_VERSION_FEAT_HSv5 0x010300 +#if defined(__cplusplus) && __cplusplus > 201406 +#define SRT_HAVE_CXX17 1 +#else +#define SRT_HAVE_CXX17 0 +#endif + + +// Standard attributes + // When compiling in C++17 mode, use the standard C++17 attributes // (out of these, only [[deprecated]] is supported in C++14, so // for all lesser standard use compiler-specific attributes). -#if defined(SRT_NO_DEPRECATED) - -#define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED -#define SRT_ATR_NODISCARD - -#elif defined(__cplusplus) && __cplusplus > 201406 +#if SRT_HAVE_CXX17 +// Unused: DO NOT issue a warning if this entity is unused. #define SRT_ATR_UNUSED [[maybe_unused]] -#define SRT_ATR_DEPRECATED [[deprecated]] + +// Nodiscard: issue a warning if the return value was discarded. #define SRT_ATR_NODISCARD [[nodiscard]] // GNUG is GNU C/C++; this syntax is also supported by Clang -#elif defined( __GNUC__) +#elif defined(__GNUC__) #define SRT_ATR_UNUSED __attribute__((unused)) -#define SRT_ATR_DEPRECATED __attribute__((deprecated)) #define SRT_ATR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define SRT_ATR_UNUSED __pragma(warning(suppress: 4100 4101)) +#define SRT_ATR_NODISCARD _Check_return_ #else #define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED #define SRT_ATR_NODISCARD #endif + +// DEPRECATED attributes + +// There's needed DEPRECATED and DEPRECATED_PX, as some compilers require them +// before the entity, others after the entity. +// The *_PX version is the prefix attribute, which applies only +// to functions (Microsoft compilers). + +// When deprecating a function, mark it: +// +// SRT_ATR_DEPRECATED_PX retval function(arguments) SRT_ATR_DEPRECATED; +// + +// When SRT_NO_DEPRECATED defined, do not issue any deprecation warnings. +// Regardless of the compiler type. +#if defined(SRT_NO_DEPRECATED) + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX + +#elif SRT_HAVE_CXX17 + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX [[deprecated]] + +// GNUG is GNU C/C++; this syntax is also supported by Clang +#elif defined(__GNUC__) +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SRT_ATR_DEPRECATED_PX __declspec(deprecated) +#define SRT_ATR_DEPRECATED // no postfix-type modifier +#else +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED +#endif + #ifdef __cplusplus extern "C" { #endif -typedef int SRTSOCKET; // SRTSOCKET is a typedef to int anyway, and it's not even in UDT namespace :) +typedef int32_t SRTSOCKET; + +// The most significant bit 31 (sign bit actually) is left unused, +// so that all people who check the value for < 0 instead of -1 +// still get what they want. The bit 30 is reserved for marking +// the "socket group". Most of the API functions should work +// transparently with the socket descriptor designating a single +// socket or a socket group. +static const int32_t SRTGROUP_MASK = (1 << 30); #ifdef _WIN32 - #ifndef __MINGW__ - typedef SOCKET SYSSOCKET; - #else - typedef int SYSSOCKET; - #endif + typedef SOCKET SYSSOCKET; #else typedef int SYSSOCKET; #endif +#ifndef ENABLE_BONDING +#define ENABLE_BONDING 0 +#endif + typedef SYSSOCKET UDPSOCKET; @@ -141,8 +188,7 @@ typedef enum SRT_SOCKOPT { SRTO_LINGER = 7, // waiting for unsent data when closing SRTO_UDP_SNDBUF = 8, // UDP sending buffer size SRTO_UDP_RCVBUF = 9, // UDP receiving buffer size - // XXX Free space for 2 options - // after deprecated ones are removed + // (some space left) SRTO_RENDEZVOUS = 12, // rendezvous connection mode SRTO_SNDTIMEO = 13, // send() timeout SRTO_RCVTIMEO = 14, // recv() timeout @@ -155,11 +201,10 @@ typedef enum SRT_SOCKOPT { SRTO_SENDER = 21, // Sender mode (independent of conn mode), for encryption, tsbpd handshake. SRTO_TSBPDMODE = 22, // Enable/Disable TsbPd. Enable -> Tx set origin timestamp, Rx deliver packet at origin time + delay SRTO_LATENCY = 23, // NOT RECOMMENDED. SET: to both SRTO_RCVLATENCY and SRTO_PEERLATENCY. GET: same as SRTO_RCVLATENCY. - SRTO_TSBPDDELAY = 23, // DEPRECATED. ALIAS: SRTO_LATENCY SRTO_INPUTBW = 24, // Estimated input stream rate. SRTO_OHEADBW, // MaxBW ceiling based on % over input stream rate. Applies when UDT_MAXBW=0 (auto). - SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto - SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (128-bit) + SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase (must be 10..79 characters, or empty to disable encryption) + SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (AES-128) SRTO_KMSTATE, // Key Material exchange status (UDT_SRTKmState) SRTO_IPTTL = 29, // IP Time To Live (passthru for system sockopt IPPROTO_IP/IP_TTL) SRTO_IPTOS, // IP Type of Service (passthru for system sockopt IPPROTO_IP/IP_TOS) @@ -168,10 +213,10 @@ typedef enum SRT_SOCKOPT { SRTO_NAKREPORT = 33, // Enable receiver to send periodic NAK reports SRTO_VERSION = 34, // Local SRT Version SRTO_PEERVERSION, // Peer SRT Version (from SRT Handshake) - SRTO_CONNTIMEO = 36, // Connect timeout in msec. Ccaller default: 3000, rendezvous (x 10) - // deprecated: SRTO_TWOWAYDATA, SRTO_SNDPBKEYLEN, SRTO_RCVPBKEYLEN (@c below) - _DEPRECATED_SRTO_SNDPBKEYLEN = 38, // (needed to use inside the code without generating -Wswitch) - // + SRTO_CONNTIMEO = 36, // Connect timeout in msec. Caller default: 3000, rendezvous (x 10) + SRTO_DRIFTTRACER = 37, // Enable or disable drift tracer + SRTO_MININPUTBW = 38, // Minimum estimate of input stream rate. + // (some space left) SRTO_SNDKMSTATE = 40, // (GET) the current state of the encryption at the peer side SRTO_RCVKMSTATE, // (GET) the current state of the encryption at the agent side SRTO_LOSSMAXTTL, // Maximum possible packet reorder tolerance (number of packets to receive after loss to send lossreport) @@ -188,15 +233,40 @@ typedef enum SRT_SOCKOPT { SRTO_ENFORCEDENCRYPTION, // Connection to be rejected or quickly broken when one side encryption set or bad password SRTO_IPV6ONLY, // IPV6_V6ONLY mode SRTO_PEERIDLETIMEO, // Peer-idle timeout (max time of silence heard from peer) in [ms] - // (some space left) - SRTO_PACKETFILTER = 60 // Add and configure a packet filter + SRTO_BINDTODEVICE, // Forward the SOL_SOCKET/SO_BINDTODEVICE option on socket (pass packets only from that device) + SRTO_GROUPCONNECT, // Set on a listener to allow group connection (ENABLE_BONDING) + SRTO_GROUPMINSTABLETIMEO, // Minimum Link Stability timeout (backup mode) in milliseconds (ENABLE_BONDING) + SRTO_GROUPTYPE, // Group type to which an accepted socket is about to be added, available in the handshake (ENABLE_BONDING) + SRTO_PACKETFILTER = 60, // Add and configure a packet filter + SRTO_RETRANSMITALGO = 61, // An option to select packet retransmission algorithm +#ifdef ENABLE_AEAD_API_PREVIEW + SRTO_CRYPTOMODE = 62, // Encryption cipher mode (AES-CTR, AES-GCM, ...). +#endif +#ifdef ENABLE_MAXREXMITBW + SRTO_MAXREXMITBW = 63, // Maximum bandwidth limit for retransmision (Bytes/s) +#endif + + SRTO_E_SIZE // Always last element, not a valid option. } SRT_SOCKOPT; #ifdef __cplusplus -typedef SRT_ATR_DEPRECATED SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED; + +#if __cplusplus > 199711L // C++11 + // Newer compilers report error when [[deprecated]] is applied to types, + // and C++11 and higher uses this. + // Note that this doesn't exactly use the 'deprecated' attribute, + // as it's introduced in C++14. What is actually used here is the + // fact that unknown attributes are ignored, but still warned about. + // This should only catch an eye - and that's what it does. +#define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT [[deprecated]])value) +#else + // Older (pre-C++11) compilers use gcc deprecated applied to a typedef + typedef SRT_ATR_DEPRECATED_PX SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED SRT_ATR_DEPRECATED; #define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT_DEPRECATED)value) +#endif + #else @@ -213,46 +283,9 @@ enum SRT_ATR_DEPRECATED SRT_SOCKOPT_DEPRECATED #define SRT_DEPRECATED_OPTION(value) ((enum SRT_SOCKOPT_DEPRECATED)value) #endif -// DEPRECATED OPTIONS: - -// SRTO_TWOWAYDATA: not to be used. SRT connection is always bidirectional if -// both clients support HSv5 - that is, since version 1.3.0. This flag was -// introducted around 1.2.0 version when full bidirectional support was added, -// but the bidirectional feature was decided no to be enabled due to huge -// differences between bidirectional support (especially concerning encryption) -// with HSv4 and HSv5 (that is, HSv4 was decided to remain unidirectional only, -// even though partial support is already provided in this version). - -#define SRTO_TWOWAYDATA SRT_DEPRECATED_OPTION(37) - -// This has been deprecated a long time ago, treat this as never implemented. -// The value is also already reused for another option. -#define SRTO_TSBPDMAXLAG SRT_DEPRECATED_OPTION(32) - -// This option is a derivative from UDT; the mechanism that uses it is now -// settable by SRTO_CONGESTION, or more generally by SRTO_TRANSTYPE. The freed -// number has been reused for a read-only option SRTO_ISN. This option should -// have never been used anywhere, just for safety this is temporarily declared -// as deprecated. -#define SRTO_CC SRT_DEPRECATED_OPTION(3) - -// These two flags were derived from UDT, but they were never used. -// Probably it didn't make sense anyway. The maximum size of the message -// in File/Message mode is defined by SRTO_SNDBUF, and the MSGTTL is -// a parameter used in `srt_sendmsg` and `srt_sendmsg2`. -#define SRTO_MAXMSG SRT_DEPRECATED_OPTION(10) -#define SRTO_MSGTTL SRT_DEPRECATED_OPTION(11) - -// These flags come from an older experimental implementation of bidirectional -// encryption support, which were used two different SEKs, KEKs and passphrases -// per direction. The current implementation uses just one in both directions, -// so SRTO_PBKEYLEN should be used for both cases. -#define SRTO_SNDPBKEYLEN SRT_DEPRECATED_OPTION(38) -#define SRTO_RCVPBKEYLEN SRT_DEPRECATED_OPTION(39) - -// Keeping old name for compatibility (deprecated) -#define SRTO_SMOOTHER SRT_DEPRECATED_OPTION(47) -#define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) +// Note that there are no deprecated options at the moment, but the mechanism +// stays so that it can be used in future. Example: +// #define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) typedef enum SRT_TRANSTYPE { @@ -295,9 +328,7 @@ struct CBytePerfMon int pktRcvUndecryptTotal; // number of undecrypted packets uint64_t byteSentTotal; // total number of sent data bytes, including retransmissions uint64_t byteRecvTotal; // total number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLossTotal; // total number of lost bytes -#endif uint64_t byteRetransTotal; // total number of retransmitted bytes uint64_t byteSndDropTotal; // number of too-late-to-send dropped bytes uint64_t byteRcvDropTotal; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -327,9 +358,7 @@ struct CBytePerfMon int pktRcvUndecrypt; // number of undecrypted packets uint64_t byteSent; // number of sent data bytes, including retransmissions uint64_t byteRecv; // number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLoss; // number of retransmitted bytes -#endif uint64_t byteRetrans; // number of retransmitted bytes uint64_t byteSndDrop; // number of too-late-to-send dropped bytes uint64_t byteRcvDrop; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -370,6 +399,20 @@ struct CBytePerfMon int pktRcvFilterLoss; // number of packet loss not coverable by filter int pktReorderTolerance; // packet reorder tolerance value //< + + // New stats in 1.5.0 + + // Total + int64_t pktSentUniqueTotal; // total number of data packets sent by the application + int64_t pktRecvUniqueTotal; // total number of packets to be received by the application + uint64_t byteSentUniqueTotal; // total number of data bytes, sent by the application + uint64_t byteRecvUniqueTotal; // total number of data bytes to be received by the application + + // Local + int64_t pktSentUnique; // number of data packets sent by the application + int64_t pktRecvUnique; // number of packets to be received by the application + uint64_t byteSentUnique; // number of data bytes, sent by the application + uint64_t byteRecvUnique; // number of data bytes to be received by the application }; //////////////////////////////////////////////////////////////////////////////// @@ -399,12 +442,14 @@ enum CodeMinor MN_REJECTED = 2, MN_NORES = 3, MN_SECURITY = 4, + MN_CLOSED = 5, // MJ_CONNECTION MN_CONNLOST = 1, MN_NOCONN = 2, // MJ_SYSTEMRES MN_THREAD = 1, MN_MEMORY = 2, + MN_OBJECT = 3, // MJ_FILESYSTEM MN_SEEKGFAIL = 1, MN_READFAIL = 2, @@ -424,6 +469,8 @@ enum CodeMinor MN_BUSY = 11, MN_XSIZE = 12, MN_EIDINVAL = 13, + MN_EEMPTY = 14, + MN_BUSYPORT = 15, // MJ_AGAIN MN_WRAVAIL = 1, MN_RDAVAIL = 2, @@ -431,12 +478,10 @@ enum CodeMinor MN_CONGESTION = 4 }; -static const enum CodeMinor MN_ISSTREAM SRT_ATR_DEPRECATED = (enum CodeMinor)(9); -static const enum CodeMinor MN_ISDGRAM SRT_ATR_DEPRECATED = (enum CodeMinor)(10); // Stupid, but effective. This will be #undefined, so don't worry. -#define MJ(major) (1000 * MJ_##major) -#define MN(major, minor) (1000 * MJ_##major + MN_##minor) +#define SRT_EMJ(major) (1000 * MJ_##major) +#define SRT_EMN(major, minor) (1000 * MJ_##major + MN_##minor) // Some better way to define it, and better for C language. typedef enum SRT_ERRNO @@ -444,55 +489,56 @@ typedef enum SRT_ERRNO SRT_EUNKNOWN = -1, SRT_SUCCESS = MJ_SUCCESS, - SRT_ECONNSETUP = MJ(SETUP), - SRT_ENOSERVER = MN(SETUP, TIMEOUT), - SRT_ECONNREJ = MN(SETUP, REJECTED), - SRT_ESOCKFAIL = MN(SETUP, NORES), - SRT_ESECFAIL = MN(SETUP, SECURITY), - - SRT_ECONNFAIL = MJ(CONNECTION), - SRT_ECONNLOST = MN(CONNECTION, CONNLOST), - SRT_ENOCONN = MN(CONNECTION, NOCONN), - - SRT_ERESOURCE = MJ(SYSTEMRES), - SRT_ETHREAD = MN(SYSTEMRES, THREAD), - SRT_ENOBUF = MN(SYSTEMRES, MEMORY), - - SRT_EFILE = MJ(FILESYSTEM), - SRT_EINVRDOFF = MN(FILESYSTEM, SEEKGFAIL), - SRT_ERDPERM = MN(FILESYSTEM, READFAIL), - SRT_EINVWROFF = MN(FILESYSTEM, SEEKPFAIL), - SRT_EWRPERM = MN(FILESYSTEM, WRITEFAIL), - - SRT_EINVOP = MJ(NOTSUP), - SRT_EBOUNDSOCK = MN(NOTSUP, ISBOUND), - SRT_ECONNSOCK = MN(NOTSUP, ISCONNECTED), - SRT_EINVPARAM = MN(NOTSUP, INVAL), - SRT_EINVSOCK = MN(NOTSUP, SIDINVAL), - SRT_EUNBOUNDSOCK = MN(NOTSUP, ISUNBOUND), - SRT_ENOLISTEN = MN(NOTSUP, NOLISTEN), - SRT_ERDVNOSERV = MN(NOTSUP, ISRENDEZVOUS), - SRT_ERDVUNBOUND = MN(NOTSUP, ISRENDUNBOUND), - SRT_EINVALMSGAPI = MN(NOTSUP, INVALMSGAPI), - SRT_EINVALBUFFERAPI = MN(NOTSUP, INVALBUFFERAPI), - SRT_EDUPLISTEN = MN(NOTSUP, BUSY), - SRT_ELARGEMSG = MN(NOTSUP, XSIZE), - SRT_EINVPOLLID = MN(NOTSUP, EIDINVAL), - - SRT_EASYNCFAIL = MJ(AGAIN), - SRT_EASYNCSND = MN(AGAIN, WRAVAIL), - SRT_EASYNCRCV = MN(AGAIN, RDAVAIL), - SRT_ETIMEOUT = MN(AGAIN, XMTIMEOUT), - SRT_ECONGEST = MN(AGAIN, CONGESTION), - - SRT_EPEERERR = MJ(PEERERROR) + SRT_ECONNSETUP = SRT_EMJ(SETUP), + SRT_ENOSERVER = SRT_EMN(SETUP, TIMEOUT), + SRT_ECONNREJ = SRT_EMN(SETUP, REJECTED), + SRT_ESOCKFAIL = SRT_EMN(SETUP, NORES), + SRT_ESECFAIL = SRT_EMN(SETUP, SECURITY), + SRT_ESCLOSED = SRT_EMN(SETUP, CLOSED), + + SRT_ECONNFAIL = SRT_EMJ(CONNECTION), + SRT_ECONNLOST = SRT_EMN(CONNECTION, CONNLOST), + SRT_ENOCONN = SRT_EMN(CONNECTION, NOCONN), + + SRT_ERESOURCE = SRT_EMJ(SYSTEMRES), + SRT_ETHREAD = SRT_EMN(SYSTEMRES, THREAD), + SRT_ENOBUF = SRT_EMN(SYSTEMRES, MEMORY), + SRT_ESYSOBJ = SRT_EMN(SYSTEMRES, OBJECT), + + SRT_EFILE = SRT_EMJ(FILESYSTEM), + SRT_EINVRDOFF = SRT_EMN(FILESYSTEM, SEEKGFAIL), + SRT_ERDPERM = SRT_EMN(FILESYSTEM, READFAIL), + SRT_EINVWROFF = SRT_EMN(FILESYSTEM, SEEKPFAIL), + SRT_EWRPERM = SRT_EMN(FILESYSTEM, WRITEFAIL), + + SRT_EINVOP = SRT_EMJ(NOTSUP), + SRT_EBOUNDSOCK = SRT_EMN(NOTSUP, ISBOUND), + SRT_ECONNSOCK = SRT_EMN(NOTSUP, ISCONNECTED), + SRT_EINVPARAM = SRT_EMN(NOTSUP, INVAL), + SRT_EINVSOCK = SRT_EMN(NOTSUP, SIDINVAL), + SRT_EUNBOUNDSOCK = SRT_EMN(NOTSUP, ISUNBOUND), + SRT_ENOLISTEN = SRT_EMN(NOTSUP, NOLISTEN), + SRT_ERDVNOSERV = SRT_EMN(NOTSUP, ISRENDEZVOUS), + SRT_ERDVUNBOUND = SRT_EMN(NOTSUP, ISRENDUNBOUND), + SRT_EINVALMSGAPI = SRT_EMN(NOTSUP, INVALMSGAPI), + SRT_EINVALBUFFERAPI = SRT_EMN(NOTSUP, INVALBUFFERAPI), + SRT_EDUPLISTEN = SRT_EMN(NOTSUP, BUSY), + SRT_ELARGEMSG = SRT_EMN(NOTSUP, XSIZE), + SRT_EINVPOLLID = SRT_EMN(NOTSUP, EIDINVAL), + SRT_EPOLLEMPTY = SRT_EMN(NOTSUP, EEMPTY), + SRT_EBINDCONFLICT = SRT_EMN(NOTSUP, BUSYPORT), + + SRT_EASYNCFAIL = SRT_EMJ(AGAIN), + SRT_EASYNCSND = SRT_EMN(AGAIN, WRAVAIL), + SRT_EASYNCRCV = SRT_EMN(AGAIN, RDAVAIL), + SRT_ETIMEOUT = SRT_EMN(AGAIN, XMTIMEOUT), + SRT_ECONGEST = SRT_EMN(AGAIN, CONGESTION), + + SRT_EPEERERR = SRT_EMJ(PEERERROR) } SRT_ERRNO; -static const SRT_ERRNO SRT_EISSTREAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALMSGAPI); -static const SRT_ERRNO SRT_EISDGRAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALBUFFERAPI); - -#undef MJ -#undef MN +#undef SRT_EMJ +#undef SRT_EMN enum SRT_REJECT_REASON { @@ -510,56 +556,173 @@ enum SRT_REJECT_REASON SRT_REJ_UNSECURE, // password required or unexpected SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision SRT_REJ_CONGESTION, // incompatible congestion-controller type - SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_GROUP, // incompatible group + SRT_REJ_TIMEOUT, // connection timeout +#ifdef ENABLE_AEAD_API_PREVIEW + SRT_REJ_CRYPTO, // conflicting cryptographic configurations +#endif - SRT_REJ__SIZE, + SRT_REJ_E_SIZE, }; +// XXX This value remains for some time, but it's deprecated +// Planned deprecation removal: rel1.6.0. +#define SRT_REJ__SIZE SRT_REJ_E_SIZE + +// Reject category codes: + +#define SRT_REJC_VALUE(code) (1000 * (code/1000)) +#define SRT_REJC_INTERNAL 0 // Codes from above SRT_REJECT_REASON enum +#define SRT_REJC_PREDEFINED 1000 // Standard server error codes +#define SRT_REJC_USERDEFINED 2000 // User defined error codes + + // Logging API - specialization for SRT. -// Define logging functional areas for log selection. -// Use values greater than 0. Value 0 is reserved for LOGFA_GENERAL, -// which is considered always enabled. +// WARNING: This part is generated. // Logger Functional Areas // Note that 0 is "general". +// Values 0* - general, unqualified +// Values 1* - control +// Values 2* - receiving +// Values 3* - sending +// Values 4* - management + // Made by #define so that it's available also for C API. -#define SRT_LOGFA_GENERAL 0 -#define SRT_LOGFA_BSTATS 1 -#define SRT_LOGFA_CONTROL 2 -#define SRT_LOGFA_DATA 3 -#define SRT_LOGFA_TSBPD 4 -#define SRT_LOGFA_REXMIT 5 -#define SRT_LOGFA_HAICRYPT 6 -#define SRT_LOGFA_CONGEST 7 - -// To make a typical int32_t size, although still use std::bitset. + +// Use ../scripts/generate-logging-defs.tcl to regenerate. + +// SRT_LOGFA BEGIN GENERATED SECTION { + +#define SRT_LOGFA_GENERAL 0 // gglog: General uncategorized log, for serious issues only +#define SRT_LOGFA_SOCKMGMT 1 // smlog: Socket create/open/close/configure activities +#define SRT_LOGFA_CONN 2 // cnlog: Connection establishment and handshake +#define SRT_LOGFA_XTIMER 3 // xtlog: The checkTimer and around activities +#define SRT_LOGFA_TSBPD 4 // tslog: The TsBPD thread +#define SRT_LOGFA_RSRC 5 // rslog: System resource allocation and management + +#define SRT_LOGFA_CONGEST 7 // cclog: Congestion control module +#define SRT_LOGFA_PFILTER 8 // pflog: Packet filter module + +#define SRT_LOGFA_API_CTRL 11 // aclog: API part for socket and library managmenet + +#define SRT_LOGFA_QUE_CTRL 13 // qclog: Queue control activities + +#define SRT_LOGFA_EPOLL_UPD 16 // eilog: EPoll, internal update activities + +#define SRT_LOGFA_API_RECV 21 // arlog: API part for receiving +#define SRT_LOGFA_BUF_RECV 22 // brlog: Buffer, receiving side +#define SRT_LOGFA_QUE_RECV 23 // qrlog: Queue, receiving side +#define SRT_LOGFA_CHN_RECV 24 // krlog: CChannel, receiving side +#define SRT_LOGFA_GRP_RECV 25 // grlog: Group, receiving side + +#define SRT_LOGFA_API_SEND 31 // aslog: API part for sending +#define SRT_LOGFA_BUF_SEND 32 // bslog: Buffer, sending side +#define SRT_LOGFA_QUE_SEND 33 // qslog: Queue, sending side +#define SRT_LOGFA_CHN_SEND 34 // kslog: CChannel, sending side +#define SRT_LOGFA_GRP_SEND 35 // gslog: Group, sending side + +#define SRT_LOGFA_INTERNAL 41 // inlog: Internal activities not connected directly to a socket + +#define SRT_LOGFA_QUE_MGMT 43 // qmlog: Queue, management part +#define SRT_LOGFA_CHN_MGMT 44 // kmlog: CChannel, management part +#define SRT_LOGFA_GRP_MGMT 45 // gmlog: Group, management part +#define SRT_LOGFA_EPOLL_API 46 // ealog: EPoll, API part + +#define SRT_LOGFA_HAICRYPT 6 // hclog: Haicrypt module area +#define SRT_LOGFA_APPLOG 10 // aplog: Applications + +// } SRT_LOGFA END GENERATED SECTION + +// To make a typical int64_t size, although still use std::bitset. // C API will carry it over. -#define SRT_LOGFA_LASTNONE 31 +#define SRT_LOGFA_LASTNONE 63 enum SRT_KM_STATE { - SRT_KM_S_UNSECURED = 0, //No encryption - SRT_KM_S_SECURING = 1, //Stream encrypted, exchanging Keying Material - SRT_KM_S_SECURED = 2, //Stream encrypted, keying Material exchanged, decrypting ok. - SRT_KM_S_NOSECRET = 3, //Stream encrypted and no secret to decrypt Keying Material - SRT_KM_S_BADSECRET = 4 //Stream encrypted and wrong secret, cannot decrypt Keying Material + SRT_KM_S_UNSECURED = 0, // No encryption + SRT_KM_S_SECURING = 1, // Stream encrypted, exchanging Keying Material + SRT_KM_S_SECURED = 2, // Stream encrypted, keying Material exchanged, decrypting ok. + SRT_KM_S_NOSECRET = 3, // Stream encrypted and no secret to decrypt Keying Material + SRT_KM_S_BADSECRET = 4 // Stream encrypted and wrong secret is used, cannot decrypt Keying Material +#ifdef ENABLE_AEAD_API_PREVIEW + ,SRT_KM_S_BADCRYPTOMODE = 5 // Stream encrypted but wrong cryptographic mode is used, cannot decrypt. Since v1.5.2. +#endif }; enum SRT_EPOLL_OPT { SRT_EPOLL_OPT_NONE = 0x0, // fallback - // this values are defined same as linux epoll.h + + // Values intended to be the same as in ``. // so that if system values are used by mistake, they should have the same effect + // This applies to: IN, OUT, ERR and ET. + + /// Ready for 'recv' operation: + /// + /// - For stream mode it means that at least 1 byte is available. + /// In this mode the buffer may extract only a part of the packet, + /// leaving next data possible for extraction later. + /// + /// - For message mode it means that there is at least one packet + /// available (this may change in future, as it is desired that + /// one full message should only wake up, not single packet of a + /// not yet extractable message). + /// + /// - For live mode it means that there's at least one packet + /// ready to play. + /// + /// - For listener sockets, this means that there is a new connection + /// waiting for pickup through the `srt_accept()` call, that is, + /// the next call to `srt_accept()` will succeed without blocking + /// (see an alias SRT_EPOLL_ACCEPT below). SRT_EPOLL_IN = 0x1, + + /// Ready for 'send' operation. + /// + /// - For stream mode it means that there's a free space in the + /// sender buffer for at least 1 byte of data. The next send + /// operation will only allow to send as much data as it is free + /// space in the buffer. + /// + /// - For message mode it means that there's a free space for at + /// least one UDP packet. The edge-triggered mode can be used to + /// pick up updates as the free space in the sender buffer grows. + /// + /// - For live mode it means that there's a free space for at least + /// one UDP packet. On the other hand, no readiness for OUT usually + /// means an extraordinary congestion on the link, meaning also that + /// you should immediately slow down the sending rate or you may get + /// a connection break soon. + /// + /// - For non-blocking sockets used with `srt_connect*` operation, + /// this flag simply means that the connection was established. SRT_EPOLL_OUT = 0x4, + + /// The socket has encountered an error in the last operation + /// and the next operation on that socket will end up with error. + /// You can retry the operation, but getting the error from it + /// is certain, so you may as well close the socket. SRT_EPOLL_ERR = 0x8, + + // To avoid confusion in the internal code, the following + // duplicates are introduced to improve clarity. + SRT_EPOLL_CONNECT = SRT_EPOLL_OUT, + SRT_EPOLL_ACCEPT = SRT_EPOLL_IN, + + SRT_EPOLL_UPDATE = 0x10, SRT_EPOLL_ET = 1u << 31 }; // These are actually flags - use a bit container: typedef int32_t SRT_EPOLL_T; +// Define which epoll flags determine events. All others are special flags. +#define SRT_EPOLL_EVENTTYPES (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_UPDATE | SRT_EPOLL_ERR) +#define SRT_EPOLL_ETONLY (SRT_EPOLL_UPDATE) + enum SRT_EPOLL_FLAGS { /// This allows the EID container to be empty when calling the waiting @@ -582,17 +745,8 @@ inline SRT_EPOLL_OPT operator|(SRT_EPOLL_OPT a1, SRT_EPOLL_OPT a2) return SRT_EPOLL_OPT( (int)a1 | (int)a2 ); } -inline bool operator&(int flags, SRT_EPOLL_OPT eflg) -{ - // Using an enum prevents treating int automatically as enum, - // requires explicit enum to be passed here, and minimizes the - // risk that the right side value will contain multiple flags. - return (flags & int(eflg)) != 0; -} #endif - - typedef struct CBytePerfMon SRT_TRACEBSTATS; static const SRTSOCKET SRT_INVALID_SOCK = -1; @@ -605,18 +759,32 @@ SRT_API int srt_cleanup(void); // // Socket operations // -SRT_API SRTSOCKET srt_socket (int af, int type, int protocol); -SRT_API SRTSOCKET srt_create_socket(); +// DEPRECATED: srt_socket with 3 arguments. All these arguments are ignored +// and socket creation doesn't need any arguments. Use srt_create_socket(). +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX SRT_API SRTSOCKET srt_socket(int, int, int) SRT_ATR_DEPRECATED; +SRT_API SRTSOCKET srt_create_socket(void); + SRT_API int srt_bind (SRTSOCKET u, const struct sockaddr* name, int namelen); -SRT_API int srt_bind_peerof (SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int srt_bind_acquire (SRTSOCKET u, UDPSOCKET sys_udp_sock); +// Old name of srt_bind_acquire(), please don't use +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX static inline int srt_bind_peerof(SRTSOCKET u, UDPSOCKET sys_udp_sock) SRT_ATR_DEPRECATED; +static inline int srt_bind_peerof (SRTSOCKET u, UDPSOCKET sys_udp_sock) { return srt_bind_acquire(u, sys_udp_sock); } SRT_API int srt_listen (SRTSOCKET u, int backlog); SRT_API SRTSOCKET srt_accept (SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API SRTSOCKET srt_accept_bond (const SRTSOCKET listeners[], int lsize, int64_t msTimeOut); typedef int srt_listen_callback_fn (void* opaq, SRTSOCKET ns, int hsversion, const struct sockaddr* peeraddr, const char* streamid); SRT_API int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); +typedef void srt_connect_callback_fn (void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); +SRT_API int srt_connect_callback(SRTSOCKET clr, srt_connect_callback_fn* hook_fn, void* hook_opaque); SRT_API int srt_connect (SRTSOCKET u, const struct sockaddr* name, int namelen); SRT_API int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +SRT_API int srt_connect_bind (SRTSOCKET u, const struct sockaddr* source, + const struct sockaddr* target, int len); SRT_API int srt_rendezvous (SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, const struct sockaddr* remote_name, int remote_namelen); + SRT_API int srt_close (SRTSOCKET u); SRT_API int srt_getpeername (SRTSOCKET u, struct sockaddr* name, int* namelen); SRT_API int srt_getsockname (SRTSOCKET u, struct sockaddr* name, int* namelen); @@ -625,19 +793,34 @@ SRT_API int srt_setsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCK SRT_API int srt_getsockflag (SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); SRT_API int srt_setsockflag (SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); +typedef struct SRT_SocketGroupData_ SRT_SOCKGROUPDATA; -// XXX Note that the srctime functionality doesn't work yet and needs fixing. typedef struct SRT_MsgCtrl_ { int flags; // Left for future - int msgttl; // TTL for a message, default -1 (no TTL limitation) + int msgttl; // TTL for a message (millisec), default -1 (no TTL limitation) int inorder; // Whether a message is allowed to supersede partially lost one. Unused in stream and live mode. int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame - uint64_t srctime; // source timestamp (usec), 0: use internal time + int64_t srctime; // source time since epoch (usec), 0: use internal time (sender) int32_t pktseq; // sequence number of the first packet in received message (unused for sending) int32_t msgno; // message number (output value for both sending and receiving) + SRT_SOCKGROUPDATA* grpdata; + size_t grpdata_size; } SRT_MSGCTRL; +// Trap representation for sequence and message numbers +// This value means that this is "unset", and it's never +// a result of an operation made on this number. +static const int32_t SRT_SEQNO_NONE = -1; // -1: no seq (0 is a valid seqno!) +static const int32_t SRT_MSGNO_NONE = -1; // -1: unset +static const int32_t SRT_MSGNO_CONTROL = 0; // 0: control (used by packet filter) + +static const int SRT_MSGTTL_INF = -1; // unlimited TTL specification for message TTL + +// XXX Might be useful also other special uses of -1: +// - -1 as infinity for srt_epoll_wait +// - -1 as a trap index value used in list.cpp + // You are free to use either of these two methods to set SRT_MSGCTRL object // to default values: either call srt_msgctrl_init(&obj) or obj = srt_msgctrl_default. SRT_API void srt_msgctrl_init(SRT_MSGCTRL* mctrl); @@ -657,11 +840,6 @@ SRT_API extern const SRT_MSGCTRL srt_msgctrl_default; // parameters will be filled, as needed. NULL is acceptable, in which case // the defaults are used. -// NOTE: srt_send and srt_recv have the last "..." left to allow ignore a -// deprecated and unused "flags" parameter. After confirming that all -// compat applications that pass useless 0 there are fixed, this will be -// removed. - // // Sending functions // @@ -692,16 +870,17 @@ SRT_API int srt_getlasterror(int* errno_loc); SRT_API const char* srt_strerror(int code, int errnoval); SRT_API void srt_clearlasterror(void); -// performance track -// perfmon with Byte counters for better bitrate estimation. +// Performance tracking +// Performance monitor with Byte counters for better bitrate estimation. SRT_API int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); -// permon with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. +// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. SRT_API int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); // Socket Status (for problem tracking) SRT_API SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); SRT_API int srt_epoll_create(void); +SRT_API int srt_epoll_clear_usocks(int eid); SRT_API int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); SRT_API int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_remove_usock(int eid, SRTSOCKET u); @@ -711,10 +890,14 @@ SRT_API int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); -typedef struct SRT_EPOLL_EVENT_ +typedef struct SRT_EPOLL_EVENT_STR { SRTSOCKET fd; int events; // SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR +#ifdef __cplusplus + SRT_EPOLL_EVENT_STR(SRTSOCKET s, int ev): fd(s), events(ev) {} + SRT_EPOLL_EVENT_STR(): fd(-1), events(0) {} // NOTE: allows singular values, no init. +#endif } SRT_EPOLL_EVENT; SRT_API int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); @@ -736,9 +919,88 @@ SRT_API void srt_setlogflags(int flags); SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); -SRT_API enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); -SRT_API extern const char* const srt_rejectreason_msg []; -const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); +SRT_API int srt_getrejectreason(SRTSOCKET sock); +SRT_API int srt_setrejectreason(SRTSOCKET sock, int value); +// The srt_rejectreason_msg[] array is deprecated (as unsafe). +// Planned removal: v1.6.0. +SRT_API SRT_ATR_DEPRECATED extern const char* const srt_rejectreason_msg []; +SRT_API const char* srt_rejectreason_str(int id); + +SRT_API uint32_t srt_getversion(void); + +SRT_API int64_t srt_time_now(void); + +SRT_API int64_t srt_connection_time(SRTSOCKET sock); + +// Possible internal clock types +#define SRT_SYNC_CLOCK_STDCXX_STEADY 0 // C++11 std::chrono::steady_clock +#define SRT_SYNC_CLOCK_GETTIME_MONOTONIC 1 // clock_gettime with CLOCK_MONOTONIC +#define SRT_SYNC_CLOCK_WINQPC 2 +#define SRT_SYNC_CLOCK_MACH_ABSTIME 3 +#define SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY 4 +#define SRT_SYNC_CLOCK_AMD64_RDTSC 5 +#define SRT_SYNC_CLOCK_IA32_RDTSC 6 +#define SRT_SYNC_CLOCK_IA64_ITC 7 + +SRT_API int srt_clock_type(void); + +// SRT Socket Groups API (ENABLE_BONDING) + +typedef enum SRT_GROUP_TYPE +{ + SRT_GTYPE_UNDEFINED, + SRT_GTYPE_BROADCAST, + SRT_GTYPE_BACKUP, + // ... + SRT_GTYPE_E_END +} SRT_GROUP_TYPE; + +// Free-form flags for groups +// Flags may be type-specific! +static const uint32_t SRT_GFLAG_SYNCONMSG = 1; + +typedef enum SRT_MemberStatus +{ + SRT_GST_PENDING, // The socket is created correctly, but not yet ready for getting data. + SRT_GST_IDLE, // The socket is ready to be activated + SRT_GST_RUNNING, // The socket was already activated and is in use + SRT_GST_BROKEN // The last operation broke the socket, it should be closed. +} SRT_MEMBERSTATUS; + +struct SRT_SocketGroupData_ +{ + SRTSOCKET id; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + SRT_SOCKSTATUS sockstate; + uint16_t weight; + SRT_MEMBERSTATUS memberstate; + int result; + int token; +}; + +typedef struct SRT_SocketOptionObject SRT_SOCKOPT_CONFIG; + +typedef struct SRT_GroupMemberConfig_ +{ + SRTSOCKET id; + struct sockaddr_storage srcaddr; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + uint16_t weight; + SRT_SOCKOPT_CONFIG* config; + int errorcode; + int token; +} SRT_SOCKGROUPCONFIG; + +SRT_API SRTSOCKET srt_create_group(SRT_GROUP_TYPE); +SRT_API SRTSOCKET srt_groupof(SRTSOCKET socket); +SRT_API int srt_group_data(SRTSOCKET socketgroup, SRT_SOCKGROUPDATA* output, size_t* inoutlen); + +SRT_API SRT_SOCKOPT_CONFIG* srt_create_config(void); +SRT_API void srt_delete_config(SRT_SOCKOPT_CONFIG* config /*nullable*/); +SRT_API int srt_config_add(SRT_SOCKOPT_CONFIG* config, SRT_SOCKOPT option, const void* contents, int len); + +SRT_API SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, const struct sockaddr* adr, int namelen); +SRT_API int srt_connect_group(SRTSOCKET group, SRT_SOCKGROUPCONFIG name[], int arraysize); #ifdef __cplusplus } diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt4udt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt4udt.h deleted file mode 100644 index 49f6d9f7a..000000000 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt4udt.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -written by - Haivision Systems Inc. - *****************************************************************************/ - -#ifndef SRT4UDT_H -#define SRT4UDT_H - -#ifndef INC__SRTC_H -#error "This is protected header, used by udt.h. This shouldn't be included directly" -#endif - -//undef SRT_ENABLE_ECN 1 /* Early Congestion Notification (for source bitrate control) */ - -//undef SRT_DEBUG_TSBPD_OUTJITTER 1 /* Packet Delivery histogram */ -//undef SRT_DEBUG_TSBPD_DRIFT 1 /* Debug Encoder-Decoder Drift) */ -//undef SRT_DEBUG_TSBPD_WRAP 1 /* Debug packet timestamp wraparound */ -//undef SRT_DEBUG_TLPKTDROP_DROPSEQ 1 -//undef SRT_DEBUG_SNDQ_HIGHRATE 1 - - -/* -* SRT_ENABLE_CONNTIMEO -* Option UDT_CONNTIMEO added to the API to set/get the connection timeout. -* The UDT hard coded default of 3000 msec is too small for some large RTT (satellite) use cases. -* The SRT handshake (2 exchanges) needs 2 times the RTT to complete with no packet loss. -*/ -#define SRT_ENABLE_CONNTIMEO 1 - -/* -* SRT_ENABLE_NOCWND -* Set the congestion window at its max (then disabling it) to prevent stopping transmission -* when too many packets are not acknowledged. -* The congestion windows is the maximum distance in pkts since the last acknowledged packets. -*/ -#define SRT_ENABLE_NOCWND 1 - -/* -* SRT_ENABLE_NAKREPORT -* Send periodic NAK report for more efficient retransmission instead of relying on ACK timeout -* to retransmit all non-ACKed packets, very inefficient with real-time and no congestion window. -*/ -#define SRT_ENABLE_NAKREPORT 1 - -#define SRT_ENABLE_RCVBUFSZ_MAVG 1 /* Recv buffer size moving average */ -#define SRT_ENABLE_SNDBUFSZ_MAVG 1 /* Send buffer size moving average */ -#define SRT_MAVG_SAMPLING_RATE 40 /* Max sampling rate */ - -#define SRT_ENABLE_LOSTBYTESCOUNT 1 - - -/* -* SRT_ENABLE_IPOPTS -* Enable IP TTL and ToS setting -*/ -#define SRT_ENABLE_IPOPTS 1 - - -#define SRT_ENABLE_CLOSE_SYNCH 1 - -#endif /* SRT4UDT_H */ diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_attr_defs.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_attr_defs.h new file mode 100644 index 000000000..84daabeb1 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_attr_defs.h @@ -0,0 +1,191 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v.2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +/***************************************************************************** +The file contains various planform and compiler dependent attribute definitions +used by SRT library internally. + *****************************************************************************/ + +#ifndef INC_SRT_ATTR_DEFS_H +#define INC_SRT_ATTR_DEFS_H + +// ATTRIBUTES: +// +// SRT_ATR_UNUSED: declare an entity ALLOWED to be unused (prevents warnings) +// ATR_DEPRECATED: declare an entity deprecated (compiler should warn when used) +// ATR_NOEXCEPT: The true `noexcept` from C++11, or nothing if compiling in pre-C++11 mode +// ATR_NOTHROW: In C++11: `noexcept`. In pre-C++11: `throw()`. Required for GNU libstdc++. +// ATR_CONSTEXPR: In C++11: `constexpr`. Otherwise empty. +// ATR_OVERRIDE: In C++11: `override`. Otherwise empty. +// ATR_FINAL: In C++11: `final`. Otherwise empty. + +#ifdef __GNUG__ +#define ATR_DEPRECATED __attribute__((deprecated)) +#else +#define ATR_DEPRECATED +#endif + +#if defined(__cplusplus) && __cplusplus > 199711L +#define HAVE_CXX11 1 +// For gcc 4.7, claim C++11 is supported, as long as experimental C++0x is on, +// however it's only the "most required C++11 support". +#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 // 4.7 only! +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#else +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1800 +// Microsoft Visual Studio supports C++11, but not fully, +// and still did not change the value of __cplusplus. Treat +// this special way. +// _MSC_VER == 1800 means Microsoft Visual Studio 2013. +#define HAVE_CXX11 1 +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#else +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif +#else +#define HAVE_CXX11 0 +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif // __cplusplus + +#if !HAVE_CXX11 && defined(REQUIRE_CXX11) && REQUIRE_CXX11 == 1 +#error "The currently compiled application required C++11, but your compiler doesn't support it." +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Attributes for thread safety analysis +// - Clang TSA (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutexheader). +// - MSVC SAL (partially). +// - Other compilers: none. +/////////////////////////////////////////////////////////////////////////////// +#if _MSC_VER >= 1920 +// In case of MSVC these attributes have to precede the attributed objects (variable, function). +// E.g. SRT_ATTR_GUARDED_BY(mtx) int object; +// It is tricky to annotate e.g. the following function, as clang complaints it does not know 'm'. +// SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) +// inline void enterCS(Mutex& m) { m.lock(); } +#define SRT_ATTR_CAPABILITY(expr) +#define SRT_ATTR_SCOPED_CAPABILITY +#define SRT_ATTR_GUARDED_BY(expr) _Guarded_by_(expr) +#define SRT_ATTR_PT_GUARDED_BY(expr) +#define SRT_ATTR_ACQUIRED_BEFORE(...) +#define SRT_ATTR_ACQUIRED_AFTER(...) +#define SRT_ATTR_REQUIRES(expr) _Requires_lock_held_(expr) +#define SRT_ATTR_REQUIRES2(expr1, expr2) _Requires_lock_held_(expr1) _Requires_lock_held_(expr2) +#define SRT_ATTR_REQUIRES_SHARED(...) +#define SRT_ATTR_ACQUIRE(expr) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_ACQUIRE_SHARED(...) +#define SRT_ATTR_RELEASE(expr) _Releases_lock_(expr) +#define SRT_ATTR_RELEASE_SHARED(...) +#define SRT_ATTR_RELEASE_GENERIC(...) +#define SRT_ATTR_TRY_ACQUIRE(...) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) +#define SRT_ATTR_EXCLUDES(...) +#define SRT_ATTR_ASSERT_CAPABILITY(expr) +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) +#define SRT_ATTR_RETURN_CAPABILITY(x) +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS +#else + +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define SRT_ATTR_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SRT_ATTR_SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define SRT_ATTR_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define SRT_ATTR_PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define SRT_ATTR_ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES2(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_GENERIC(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define SRT_ATTR_ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define SRT_ATTR_RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // not _MSC_VER + +#endif // INC_SRT_ATTR_DEFS_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_compat.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_compat.h new file mode 100644 index 000000000..960c1b85a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/srt_compat.h @@ -0,0 +1,109 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_COMPAT_H +#define INC_SRT_COMPAT_H + +#include +#include + +#ifndef SRT_API +#ifdef _WIN32 + #ifndef __MINGW32__ + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) + #else + #define SRT_API __declspec(dllimport) + #endif + #else + #define SRT_API + #endif + #else + #define SRT_API + #endif +#else + #define SRT_API __attribute__ ((visibility("default"))) +#endif +#endif + +#ifdef _WIN32 + // https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "Id" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "Iu" + #endif +#else + // http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "zd" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "zu" + #endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Ensures that we store the error in the buffer and return the bufer. */ +SRT_API const char * SysStrError(int errnum, char * buf, size_t buflen); + +#ifdef __cplusplus +} // extern C + + +// Extra C++ stuff. Included only in C++ mode. + + +#include +#include +inline std::string SysStrError(int errnum) +{ + char buf[1024]; + return SysStrError(errnum, buf, 1024); +} + +inline struct tm SysLocalTime(time_t tt) +{ + struct tm tms; + memset(&tms, 0, sizeof tms); +#ifdef _WIN32 + errno_t rr = localtime_s(&tms, &tt); + if (rr == 0) + return tms; +#else + + // Ignore the error, state that if something + // happened, you simply have a pre-cleared tms. + localtime_r(&tt, &tms); +#endif + + return tms; +} + + +#endif // defined C++ + +#endif // INC_SRT_COMPAT_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/stats.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/stats.h new file mode 100644 index 000000000..bce60761b --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/stats.h @@ -0,0 +1,221 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_STATS_H +#define INC_SRT_STATS_H + +#include "platform_sys.h" +#include "packet.h" + +namespace srt +{ +namespace stats +{ + +class Packets +{ +public: + Packets() : m_count(0) {} + + Packets(uint32_t num) : m_count(num) {} + + void reset() + { + m_count = 0; + } + + Packets& operator+= (const Packets& other) + { + m_count += other.m_count; + return *this; + } + + uint32_t count() const + { + return m_count; + } + +private: + uint32_t m_count; +}; + +class BytesPackets +{ +public: + BytesPackets() + : m_bytes(0) + , m_packets(0) + {} + + BytesPackets(uint64_t bytes, uint32_t n = 1) + : m_bytes(bytes) + , m_packets(n) + {} + + BytesPackets& operator+= (const BytesPackets& other) + { + m_bytes += other.m_bytes; + m_packets += other.m_packets; + return *this; + } + +public: + void reset() + { + m_packets = 0; + m_bytes = 0; + } + + void count(uint64_t bytes, size_t n = 1) + { + m_packets += (uint32_t) n; + m_bytes += bytes; + } + + uint64_t bytes() const + { + return m_bytes; + } + + uint32_t count() const + { + return m_packets; + } + + uint64_t bytesWithHdr() const + { + return m_bytes + m_packets * CPacket::SRT_DATA_HDR_SIZE; + } + +private: + uint64_t m_bytes; + uint32_t m_packets; +}; + +template +struct Metric +{ + METRIC_TYPE trace; + METRIC_TYPE total; + + void count(METRIC_TYPE val) + { + trace += val; + total += val; + } + + void reset() + { + trace.reset(); + total.reset(); + } + + void resetTrace() + { + trace.reset(); + } +}; + +/// Sender-side statistics. +struct Sender +{ + Metric sent; + Metric sentUnique; + Metric sentRetrans; // The number of data packets retransmitted by the sender. + Metric lost; // The number of packets reported lost (including repeated reports) to the sender in NAKs. + Metric dropped; // The number of data packets dropped by the sender. + + Metric sentFilterExtra; // The number of packets generate by the packet filter and sent by the sender. + + Metric recvdAck; // The number of ACK packets received by the sender. + Metric recvdNak; // The number of ACK packets received by the sender. + + void reset() + { + sent.reset(); + sentUnique.reset(); + sentRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdAck.reset(); + recvdNak.reset(); + sentFilterExtra.reset(); + } + + void resetTrace() + { + sent.resetTrace(); + sentUnique.resetTrace(); + sentRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdAck.resetTrace(); + recvdNak.resetTrace(); + sentFilterExtra.resetTrace(); + } +}; + +/// Receiver-side statistics. +struct Receiver +{ + Metric recvd; + Metric recvdUnique; + Metric recvdRetrans; // The number of retransmitted data packets received by the receiver. + Metric lost; // The number of packets detected by the receiver as lost. + Metric dropped; // The number of packets dropped by the receiver (as too-late to be delivered). + Metric recvdBelated; // The number of belated packets received (dropped as too late but eventually received). + Metric undecrypted; // The number of packets received by the receiver that failed to be decrypted. + + Metric recvdFilterExtra; // The number of filter packets (e.g. FEC) received by the receiver. + Metric suppliedByFilter; // The number of lost packets got from the packet filter at the receiver side (e.g. loss recovered by FEC). + Metric lossFilter; // The number of lost DATA packets not recovered by the packet filter at the receiver side. + + Metric sentAck; // The number of ACK packets sent by the receiver. + Metric sentNak; // The number of NACK packets sent by the receiver. + + void reset() + { + recvd.reset(); + recvdUnique.reset(); + recvdRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdBelated.reset(); + undecrypted.reset(); + recvdFilterExtra.reset(); + suppliedByFilter.reset(); + lossFilter.reset(); + sentAck.reset(); + sentNak.reset(); + } + + void resetTrace() + { + recvd.resetTrace(); + recvdUnique.resetTrace(); + recvdRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdBelated.resetTrace(); + undecrypted.resetTrace(); + recvdFilterExtra.resetTrace(); + suppliedByFilter.resetTrace(); + lossFilter.resetTrace(); + sentAck.resetTrace(); + sentNak.resetTrace(); + } +}; + +} // namespace stats +} // namespace srt + +#endif // INC_SRT_STATS_H + + diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/sync.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/sync.h new file mode 100644 index 000000000..87be6f458 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/sync.h @@ -0,0 +1,947 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +#pragma once +#ifndef INC_SRT_SYNC_H +#define INC_SRT_SYNC_H + +#include "platform_sys.h" + +#include +#include +#ifdef ENABLE_STDCXX_SYNC +#include +#include +#include +#include +#include +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_STDCXX_STEADY +#define SRT_SYNC_CLOCK_STR "STDCXX_STEADY" +#else +#include + +// Defile clock type to use +#ifdef IA32 +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA32_RDTSC +#define SRT_SYNC_CLOCK_STR "IA32_RDTSC" +#elif defined(IA64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA64_ITC +#define SRT_SYNC_CLOCK_STR "IA64_ITC" +#elif defined(AMD64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_AMD64_RDTSC +#define SRT_SYNC_CLOCK_STR "AMD64_RDTSC" +#elif defined(_WIN32) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_WINQPC +#define SRT_SYNC_CLOCK_STR "WINQPC" +#elif TARGET_OS_MAC +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_MACH_ABSTIME +#define SRT_SYNC_CLOCK_STR "MACH_ABSTIME" +#elif defined(ENABLE_MONOTONIC_CLOCK) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_GETTIME_MONOTONIC +#define SRT_SYNC_CLOCK_STR "GETTIME_MONOTONIC" +#else +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY +#define SRT_SYNC_CLOCK_STR "POSIX_GETTIMEOFDAY" +#endif + +#endif // ENABLE_STDCXX_SYNC + +#include "srt.h" +#include "utilities.h" +#include "srt_attr_defs.h" + + +namespace srt +{ + +class CUDTException; // defined in common.h + +namespace sync +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration class +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +template +using Duration = std::chrono::duration; + +#else + +/// Class template srt::sync::Duration represents a time interval. +/// It consists of a count of ticks of _Clock. +/// It is a wrapper of system timers in case of non-C++11 chrono build. +template +class Duration +{ +public: + Duration() + : m_duration(0) + { + } + + explicit Duration(int64_t d) + : m_duration(d) + { + } + +public: + inline int64_t count() const { return m_duration; } + + static Duration zero() { return Duration(); } + +public: // Relational operators + inline bool operator>=(const Duration& rhs) const { return m_duration >= rhs.m_duration; } + inline bool operator>(const Duration& rhs) const { return m_duration > rhs.m_duration; } + inline bool operator==(const Duration& rhs) const { return m_duration == rhs.m_duration; } + inline bool operator!=(const Duration& rhs) const { return m_duration != rhs.m_duration; } + inline bool operator<=(const Duration& rhs) const { return m_duration <= rhs.m_duration; } + inline bool operator<(const Duration& rhs) const { return m_duration < rhs.m_duration; } + +public: // Assignment operators + inline void operator*=(const int64_t mult) { m_duration = static_cast(m_duration * mult); } + inline void operator+=(const Duration& rhs) { m_duration += rhs.m_duration; } + inline void operator-=(const Duration& rhs) { m_duration -= rhs.m_duration; } + + inline Duration operator+(const Duration& rhs) const { return Duration(m_duration + rhs.m_duration); } + inline Duration operator-(const Duration& rhs) const { return Duration(m_duration - rhs.m_duration); } + inline Duration operator*(const int64_t& rhs) const { return Duration(m_duration * rhs); } + inline Duration operator/(const int64_t& rhs) const { return Duration(m_duration / rhs); } + +private: + // int64_t range is from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 + int64_t m_duration; +}; + +#endif // ENABLE_STDCXX_SYNC + +/////////////////////////////////////////////////////////////////////////////// +// +// TimePoint and steadt_clock classes +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +using steady_clock = std::chrono::steady_clock; + +template +using time_point = std::chrono::time_point; + +template +using TimePoint = std::chrono::time_point; + +template +inline bool is_zero(const time_point &tp) +{ + return tp.time_since_epoch() == Clock::duration::zero(); +} + +inline bool is_zero(const steady_clock::time_point& t) +{ + return t == steady_clock::time_point(); +} + +#else +template +class TimePoint; + +class steady_clock +{ +public: + typedef Duration duration; + typedef TimePoint time_point; + +public: + static time_point now(); +}; + +/// Represents a point in time +template +class TimePoint +{ +public: + TimePoint() + : m_timestamp(0) + { + } + + explicit TimePoint(uint64_t tp) + : m_timestamp(tp) + { + } + + TimePoint(const TimePoint& other) + : m_timestamp(other.m_timestamp) + { + } + + TimePoint(const Duration& duration_since_epoch) + : m_timestamp(duration_since_epoch.count()) + { + } + + ~TimePoint() {} + +public: // Relational operators + inline bool operator<(const TimePoint& rhs) const { return m_timestamp < rhs.m_timestamp; } + inline bool operator<=(const TimePoint& rhs) const { return m_timestamp <= rhs.m_timestamp; } + inline bool operator==(const TimePoint& rhs) const { return m_timestamp == rhs.m_timestamp; } + inline bool operator!=(const TimePoint& rhs) const { return m_timestamp != rhs.m_timestamp; } + inline bool operator>=(const TimePoint& rhs) const { return m_timestamp >= rhs.m_timestamp; } + inline bool operator>(const TimePoint& rhs) const { return m_timestamp > rhs.m_timestamp; } + +public: // Arithmetic operators + inline Duration operator-(const TimePoint& rhs) const + { + return Duration(m_timestamp - rhs.m_timestamp); + } + inline TimePoint operator+(const Duration& rhs) const { return TimePoint(m_timestamp + rhs.count()); } + inline TimePoint operator-(const Duration& rhs) const { return TimePoint(m_timestamp - rhs.count()); } + +public: // Assignment operators + inline void operator=(const TimePoint& rhs) { m_timestamp = rhs.m_timestamp; } + inline void operator+=(const Duration& rhs) { m_timestamp += rhs.count(); } + inline void operator-=(const Duration& rhs) { m_timestamp -= rhs.count(); } + +public: // + static inline ATR_CONSTEXPR TimePoint min() { return TimePoint(std::numeric_limits::min()); } + static inline ATR_CONSTEXPR TimePoint max() { return TimePoint(std::numeric_limits::max()); } + +public: + Duration time_since_epoch() const; + +private: + uint64_t m_timestamp; +}; + +template <> +srt::sync::Duration srt::sync::TimePoint::time_since_epoch() const; + +inline Duration operator*(const int& lhs, const Duration& rhs) +{ + return rhs * lhs; +} + +#endif // ENABLE_STDCXX_SYNC + +// NOTE: Moved the following class definitions to "atomic_clock.h" +// template +// class AtomicDuration; +// template +// class AtomicClock; + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration and timepoint conversions +// +/////////////////////////////////////////////////////////////////////////////// + +/// Function return number of decimals in a subsecond precision. +/// E.g. for a microsecond accuracy of steady_clock the return would be 6. +/// For a nanosecond accuracy of the steady_clock the return value would be 9. +int clockSubsecondPrecision(); + +#if ENABLE_STDCXX_SYNC + +inline long long count_microseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_microseconds(const steady_clock::time_point tp) +{ + return std::chrono::duration_cast(tp.time_since_epoch()).count(); +} + +inline long long count_milliseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_seconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline steady_clock::duration microseconds_from(int64_t t_us) +{ + return std::chrono::microseconds(t_us); +} + +inline steady_clock::duration milliseconds_from(int64_t t_ms) +{ + return std::chrono::milliseconds(t_ms); +} + +inline steady_clock::duration seconds_from(int64_t t_s) +{ + return std::chrono::seconds(t_s); +} + +#else + +int64_t count_microseconds(const steady_clock::duration& t); +int64_t count_milliseconds(const steady_clock::duration& t); +int64_t count_seconds(const steady_clock::duration& t); + +Duration microseconds_from(int64_t t_us); +Duration milliseconds_from(int64_t t_ms); +Duration seconds_from(int64_t t_s); + +inline bool is_zero(const TimePoint& t) +{ + return t == TimePoint(); +} + +#endif // ENABLE_STDCXX_SYNC + + +/////////////////////////////////////////////////////////////////////////////// +// +// Mutex section +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC +using Mutex = std::mutex; +using UniqueLock = std::unique_lock; +using ScopedLock = std::lock_guard; +#else +/// Mutex is a class wrapper, that should mimic the std::chrono::mutex class. +/// At the moment the extra function ref() is temporally added to allow calls +/// to pthread_cond_timedwait(). Will be removed by introducing CEvent. +class SRT_ATTR_CAPABILITY("mutex") Mutex +{ + friend class SyncEvent; + +public: + Mutex(); + ~Mutex(); + +public: + int lock() SRT_ATTR_ACQUIRE(); + int unlock() SRT_ATTR_RELEASE(); + + /// @return true if the lock was acquired successfully, otherwise false + bool try_lock() SRT_ATTR_TRY_ACQUIRE(true); + + // TODO: To be removed with introduction of the CEvent. + pthread_mutex_t& ref() { return m_mutex; } + +private: + pthread_mutex_t m_mutex; +}; + +/// A pthread version of std::chrono::scoped_lock (or lock_guard for C++11) +class SRT_ATTR_SCOPED_CAPABILITY ScopedLock +{ +public: + SRT_ATTR_ACQUIRE(m) + explicit ScopedLock(Mutex& m); + + SRT_ATTR_RELEASE() + ~ScopedLock(); + +private: + Mutex& m_mutex; +}; + +/// A pthread version of std::chrono::unique_lock +class SRT_ATTR_SCOPED_CAPABILITY UniqueLock +{ + friend class SyncEvent; + int m_iLocked; + Mutex& m_Mutex; + +public: + SRT_ATTR_ACQUIRE(m) + explicit UniqueLock(Mutex &m); + + SRT_ATTR_RELEASE() + ~UniqueLock(); + +public: + SRT_ATTR_ACQUIRE() + void lock(); + + SRT_ATTR_RELEASE() + void unlock(); + + SRT_ATTR_RETURN_CAPABILITY(m_Mutex) + Mutex* mutex(); // reflects C++11 unique_lock::mutex() +}; +#endif // ENABLE_STDCXX_SYNC + +inline void enterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) { m.lock(); } + +inline bool tryEnterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_TRY_ACQUIRE(true, m) { return m.try_lock(); } + +inline void leaveCS(Mutex& m) SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) { m.unlock(); } + +class InvertedLock +{ + Mutex& m_mtx; + +public: + SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) + InvertedLock(Mutex& m) + : m_mtx(m) + { + m_mtx.unlock(); + } + + SRT_ATTR_ACQUIRE(m_mtx) + ~InvertedLock() + { + m_mtx.lock(); + } +}; + +inline void setupMutex(Mutex&, const char*) {} +inline void releaseMutex(Mutex&) {} + +//////////////////////////////////////////////////////////////////////////////// +// +// Condition section +// +//////////////////////////////////////////////////////////////////////////////// + +class Condition +{ +public: + Condition(); + ~Condition(); + +public: + /// These functions do not align with C++11 version. They are here hopefully as a temporal solution + /// to avoud issues with static initialization of CV on windows. + void init(); + void destroy(); + +public: + /// Causes the current thread to block until the condition variable is notified + /// or a spurious wakeup occurs. + /// + /// @param lock Corresponding mutex locked by UniqueLock + void wait(UniqueLock& lock); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on *this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. When unblocked, regardless of the reason, + /// lock is reacquired and wait_for() exits. + /// + /// @returns false if the relative timeout specified by rel_time expired, + /// true otherwise (signal or spurious wake up). + /// + /// @note Calling this function if lock.mutex() + /// is not locked by the current thread is undefined behavior. + /// Calling this function if lock.mutex() is not the same mutex as the one + /// used by all other threads that are currently waiting on the same + /// condition variable is undefined behavior. + bool wait_for(UniqueLock& lock, const steady_clock::duration& rel_time); + + /// Causes the current thread to block until the condition variable is notified, + /// a specific time is reached, or a spurious wakeup occurs. + /// + /// @param[in] lock an object of type UniqueLock, which must be locked by the current thread + /// @param[in] timeout_time an object of type time_point representing the time when to stop waiting + /// + /// @returns false if the relative timeout specified by timeout_time expired, + /// true otherwise (signal or spurious wake up). + bool wait_until(UniqueLock& lock, const steady_clock::time_point& timeout_time); + + /// Calling notify_one() unblocks one of the waiting threads, + /// if any threads are waiting on this CV. + void notify_one(); + + /// Unblocks all threads currently waiting for this CV. + void notify_all(); + +private: +#if ENABLE_STDCXX_SYNC + std::condition_variable m_cv; +#else + pthread_cond_t m_cv; +#endif +}; + +inline void setupCond(Condition& cv, const char*) { cv.init(); } +inline void releaseCond(Condition& cv) { cv.destroy(); } + +/////////////////////////////////////////////////////////////////////////////// +// +// Event (CV) section +// +/////////////////////////////////////////////////////////////////////////////// + +// This class is used for condition variable combined with mutex by different ways. +// This should provide a cleaner API around locking with debug-logging inside. +class CSync +{ +protected: + Condition* m_cond; + UniqueLock* m_locker; + +public: + // Locked version: must be declared only after the declaration of UniqueLock, + // which has locked the mutex. On this delegate you should call only + // signal_locked() and pass the UniqueLock variable that should remain locked. + // Also wait() and wait_for() can be used only with this socket. + CSync(Condition& cond, UniqueLock& g) + : m_cond(&cond), m_locker(&g) + { + // XXX it would be nice to check whether the owner is also current thread + // but this can't be done portable way. + + // When constructed by this constructor, the user is expected + // to only call signal_locked() function. You should pass the same guard + // variable that you have used for construction as its argument. + } + + // COPY CONSTRUCTOR: DEFAULT! + + // Wait indefinitely, until getting a signal on CV. + void wait() + { + m_cond->wait(*m_locker); + } + + /// Block the call until either @a timestamp time achieved + /// or the conditional is signaled. + /// @param [in] delay Maximum time to wait since the moment of the call + /// @retval false if the relative timeout specified by rel_time expired, + /// @retval true if condition is signaled or spurious wake up. + bool wait_for(const steady_clock::duration& delay) + { + return m_cond->wait_for(*m_locker, delay); + } + + // Wait until the given time is achieved. + /// @param [in] exptime The target time to wait until. + /// @retval false if the target wait time is reached. + /// @retval true if condition is signal or spurious wake up. + bool wait_until(const steady_clock::time_point& exptime) + { + return m_cond->wait_until(*m_locker, exptime); + } + + // Static ad-hoc version + static void lock_notify_one(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_one(); + } + + static void lock_notify_all(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_all(); + } + + void notify_one_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_one(); + } + + void notify_all_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_all(); + } + + // The *_relaxed functions are to be used in case when you don't care + // whether the associated mutex is locked or not (you accept the case that + // a mutex isn't locked and the condition notification gets effectively + // missed), or you somehow know that the mutex is locked, but you don't + // have access to the associated UniqueLock object. This function, although + // it does the same thing as CSync::notify_one_locked etc. here for the + // user to declare explicitly that notifying is done without being + // prematurely certain that the associated mutex is locked. + // + // It is then expected that whenever these functions are used, an extra + // comment is provided to explain, why the use of the relaxed notification + // is correctly used. + + void notify_one_relaxed() { notify_one_relaxed(*m_cond); } + static void notify_one_relaxed(Condition& cond) { cond.notify_one(); } + static void notify_all_relaxed(Condition& cond) { cond.notify_all(); } +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +// XXX Do not use this class now, there's an unknown issue +// connected to object management with the use of release* functions. +// Until this is solved, stay with separate *Cond and *Lock fields. +class CEvent +{ +public: + CEvent(); + ~CEvent(); + +public: + Mutex& mutex() { return m_lock; } + Condition& cond() { return m_cond; } + +public: + /// Causes the current thread to block until + /// a specific time is reached. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_until(const steady_clock::time_point& tp); + + /// Blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// Uses internal mutex to lock. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_for(const steady_clock::duration& rel_time); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// When unblocked, regardless of the reason, lock is reacquiredand wait_for() exits. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool wait_for(UniqueLock& lk, const steady_clock::duration& rel_time); + + void lock_wait(); + + void wait(UniqueLock& lk); + + void notify_one(); + + void notify_all(); + + void lock_notify_one() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_one(); + } + + void lock_notify_all() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_all(); + } + +private: + Mutex m_lock; + Condition m_cond; +}; + + +// This class binds together the functionality of +// UniqueLock and CSync. It provides a simple interface of CSync +// while having already the UniqueLock applied in the scope, +// so a safe statement can be made about the mutex being locked +// when signalling or waiting. +class CUniqueSync: public CSync +{ + UniqueLock m_ulock; + +public: + + UniqueLock& locker() { return m_ulock; } + + CUniqueSync(Mutex& mut, Condition& cnd) + : CSync(cnd, m_ulock) + , m_ulock(mut) + { + } + + CUniqueSync(CEvent& event) + : CSync(event.cond(), m_ulock) + , m_ulock(event.mutex()) + { + } + + // These functions can be used safely because + // this whole class guarantees that whatever happens + // while its object exists is that the mutex is locked. + + void notify_one() + { + m_cond->notify_one(); + } + + void notify_all() + { + m_cond->notify_all(); + } +}; + +class CTimer +{ +public: + CTimer(); + ~CTimer(); + +public: + /// Causes the current thread to block until + /// the specified time is reached. + /// Sleep can be interrupted by calling interrupt() + /// or woken up to recheck the scheduled time by tick() + /// @param tp target time to sleep until + /// + /// @return true if the specified time was reached + /// false should never happen + bool sleep_until(steady_clock::time_point tp); + + /// Resets target wait time and interrupts waiting + /// in sleep_until(..) + void interrupt(); + + /// Wakes up waiting thread (sleep_until(..)) without + /// changing the target waiting time to force a recheck + /// of the current time in comparisson to the target time. + void tick(); + +private: + CEvent m_event; + steady_clock::time_point m_tsSchedTime; +}; + + +/// Print steady clock timepoint in a human readable way. +/// days HH:MM:SS.us [STD] +/// Example: 1D 02:12:56.123456 +/// +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTime(const steady_clock::time_point& time); + +/// Print steady clock timepoint relative to the current system time +/// Date HH:MM:SS.us [SYS] +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTimeSys(const steady_clock::time_point& time); + +enum eDurationUnit {DUNIT_S, DUNIT_MS, DUNIT_US}; + +template +struct DurationUnitName; + +template<> +struct DurationUnitName +{ + static const char* name() { return "us"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur)); } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "ms"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000.0; } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "s"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000000.0; } +}; + +template +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return Sprint(DurationUnitName::count(dur)) + DurationUnitName::name(); +} + +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return FormatDuration(dur); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// CGlobEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +class CGlobEvent +{ +public: + /// Triggers the event and notifies waiting threads. + /// Simply calls notify_one(). + static void triggerEvent(); + + /// Waits for the event to be triggered with 10ms timeout. + /// Simply calls wait_for(). + static bool waitForEvent(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CThread class +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef ENABLE_STDCXX_SYNC +typedef std::system_error CThreadException; +using CThread = std::thread; +namespace this_thread = std::this_thread; +#else // pthreads wrapper version +typedef CUDTException CThreadException; + +class CThread +{ +public: + CThread(); + /// @throws std::system_error if the thread could not be started. + CThread(void *(*start_routine) (void *), void *arg); + +#if HAVE_FULL_CXX11 + CThread& operator=(CThread &other) = delete; + CThread& operator=(CThread &&other); +#else + CThread& operator=(CThread &other); + /// To be used only in StartThread function. + /// Creates a new stread and assigns to this. + /// @throw CThreadException + void create_thread(void *(*start_routine) (void *), void *arg); +#endif + +public: // Observers + /// Checks if the CThread object identifies an active thread of execution. + /// A default constructed thread is not joinable. + /// A thread that has finished executing code, but has not yet been joined + /// is still considered an active thread of execution and is therefore joinable. + bool joinable() const; + + struct id + { + explicit id(const pthread_t t) + : value(t) + {} + + const pthread_t value; + inline bool operator==(const id& second) const + { + return pthread_equal(value, second.value) != 0; + } + }; + + /// Returns the id of the current thread. + /// In this implementation the ID is the pthread_t. + const id get_id() const { return id(m_thread); } + +public: + /// Blocks the current thread until the thread identified by *this finishes its execution. + /// If that thread has already terminated, then join() returns immediately. + /// + /// @throws std::system_error if an error occurs + void join(); + +public: // Internal + /// Calls pthread_create, throws exception on failure. + /// @throw CThreadException + void create(void *(*start_routine) (void *), void *arg); + +private: + pthread_t m_thread; +}; + +template +inline Stream& operator<<(Stream& str, const CThread::id& cid) +{ +#if defined(_WIN32) && (defined(PTW32_VERSION) || defined (__PTW32_VERSION)) + // This is a version specific for pthread-win32 implementation + // Here pthread_t type is a structure that is not convertible + // to a number at all. + return str << pthread_getw32threadid_np(cid.value); +#else + return str << cid.value; +#endif +} + +namespace this_thread +{ + const inline CThread::id get_id() { return CThread::id (pthread_self()); } + + inline void sleep_for(const steady_clock::duration& t) + { +#if !defined(_WIN32) + usleep(count_microseconds(t)); // microseconds +#else + Sleep((DWORD) count_milliseconds(t)); +#endif + } +} + +#endif + +/// StartThread function should be used to do CThread assignments: +/// @code +/// CThread a(); +/// a = CThread(func, args); +/// @endcode +/// +/// @returns true if thread was started successfully, +/// false on failure +/// +#ifdef ENABLE_STDCXX_SYNC +typedef void* (&ThreadFunc) (void*); +bool StartThread(CThread& th, ThreadFunc&& f, void* args, const std::string& name); +#else +bool StartThread(CThread& th, void* (*f) (void*), void* args, const std::string& name); +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// CThreadError class - thread local storage wrapper +// +//////////////////////////////////////////////////////////////////////////////// + +/// Set thread local error +/// @param e new CUDTException +void SetThreadLocalError(const CUDTException& e); + +/// Get thread local error +/// @returns CUDTException pointer +CUDTException& GetThreadLocalError(); + +//////////////////////////////////////////////////////////////////////////////// +// +// Random distribution functions. +// +//////////////////////////////////////////////////////////////////////////////// + +/// Generate a uniform-distributed random integer from [minVal; maxVal]. +/// If HAVE_CXX11, uses std::uniform_distribution(std::random_device). +/// @param[in] minVal minimum allowed value of the resulting random number. +/// @param[in] maxVal maximum allowed value of the resulting random number. +int genRandomInt(int minVal, int maxVal); + +} // namespace sync +} // namespace srt + +#include "atomic_clock.h" + +#endif // INC_SRT_SYNC_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/threadname.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/threadname.h new file mode 100644 index 000000000..1c064c86c --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/threadname.h @@ -0,0 +1,224 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_THREADNAME_H +#define INC_SRT_THREADNAME_H + +// NOTE: +// HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_GETNAME_NP +// HAVE_PTHREAD_GETNAME_NP +// Are detected and set in ../CMakeLists.txt. +// OS Availability of pthread_getname_np(..) and pthread_setname_np(..):: +// MacOS(10.6) +// iOS(3.2) +// AIX(7.1) +// FreeBSD(version?), OpenBSD(Version?) +// Linux-GLIBC(GLIBC-2.12). +// Linux-MUSL(MUSL-1.1.20 Partial Implementation. See below). +// MINGW-W64(4.0.6) + +#if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + || defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + #include + #if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_GETNAME_NP) + #define HAVE_PTHREAD_GETNAME_NP 1 + #endif + #if defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_SETNAME_NP) + #define HAVE_PTHREAD_SETNAME_NP 1 + #endif +#endif + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + // NOTE: + // Linux pthread_getname_np() and pthread_setname_np() became available + // in GLIBC-2.12 and later. + // Some Linux runtimes do not have pthread_getname_np(), but have + // pthread_setname_np(), for instance MUSL at least as of v1.1.20. + // So using the prctl() for Linux is more portable. + #if defined(__linux__) + #include + #endif + #include +#endif + +#include +#include +#include + +#include "common.h" +#include "sync.h" + +namespace srt { + +class ThreadName +{ + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + + class ThreadNameImpl + { + public: + static const size_t BUFSIZE = 64; + static const bool DUMMY_IMPL = false; + + static bool get(char* namebuf) + { +#if defined(__linux__) + // since Linux 2.6.11. The buffer should allow space for up to 16 + // bytes; the returned string will be null-terminated. + return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_GETNAME_NP) + return pthread_getname_np(pthread_self(), namebuf, BUFSIZE) == 0; +#else +#error "unsupported platform" +#endif + } + + static bool set(const char* name) + { + SRT_ASSERT(name != NULL); +#if defined(__linux__) + // The name can be up to 16 bytes long, including the terminating + // null byte. (If the length of the string, including the terminating + // null byte, exceeds 16 bytes, the string is silently truncated.) + return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_SETNAME_NP) + #if defined(__APPLE__) + return pthread_setname_np(name) == 0; + #else + return pthread_setname_np(pthread_self(), name) == 0; + #endif +#else +#error "unsupported platform" +#endif + } + + explicit ThreadNameImpl(const std::string& name) + : reset(false) + { + tid = pthread_self(); + + if (!get(old_name)) + return; + + reset = set(name.c_str()); + if (reset) + return; + + // Try with a shorter name. 15 is the upper limit supported by Linux, + // other platforms should support a larger value. So 15 should works + // on all platforms. + const size_t max_len = 15; + if (name.size() > max_len) + reset = set(name.substr(0, max_len).c_str()); + } + + ~ThreadNameImpl() + { + if (!reset) + return; + + // ensure it's called on the right thread + if (tid == pthread_self()) + set(old_name); + } + + private: + ThreadNameImpl(ThreadNameImpl& other); + ThreadNameImpl& operator=(const ThreadNameImpl& other); + + private: + bool reset; + pthread_t tid; + char old_name[BUFSIZE]; + }; + +#else + + class ThreadNameImpl + { + public: + static const bool DUMMY_IMPL = true; + static const size_t BUFSIZE = 64; + + static bool get(char* output) + { + // The default implementation will simply try to get the thread ID + std::ostringstream bs; + bs << "T" << sync::this_thread::get_id(); + size_t s = bs.str().copy(output, BUFSIZE - 1); + output[s] = '\0'; + return true; + } + + static bool set(const char*) { return false; } + + ThreadNameImpl(const std::string&) {} + + ~ThreadNameImpl() // just to make it "non-trivially-destructible" for compatibility with normal version + { + } + }; + +#endif // platform dependent impl + + // Why delegate to impl: + // 1. to make sure implementation on different platforms have the same interface. + // 2. it's simple to add some wrappers like get(const std::string &). + ThreadNameImpl impl; + +public: + static const bool DUMMY_IMPL = ThreadNameImpl::DUMMY_IMPL; + static const size_t BUFSIZE = ThreadNameImpl::BUFSIZE; + + /// @brief Print thread ID to the provided buffer. + /// The size of the destination buffer is assumed to be at least ThreadName::BUFSIZE. + /// @param [out] output destination buffer to get thread name + /// @return true on success, false on failure + static bool get(char* output) { + return ThreadNameImpl::get(output); + } + + static bool get(std::string& name) + { + char buf[BUFSIZE]; + bool ret = get(buf); + if (ret) + name = buf; + return ret; + } + + static bool set(const std::string& name) { return ThreadNameImpl::set(name.c_str()); } + + explicit ThreadName(const std::string& name) + : impl(name) + { + } + +private: + ThreadName(const ThreadName&); + ThreadName(const char*); + ThreadName& operator=(const ThreadName& other); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/tsbpd_time.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/tsbpd_time.h new file mode 100644 index 000000000..3483c197f --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/tsbpd_time.h @@ -0,0 +1,163 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_TSBPD_TIME_H +#define INC_SRT_TSBPD_TIME_H + +#include "platform_sys.h" +#include "sync.h" +#include "utilities.h" + +namespace srt +{ + +/// @brief TimeStamp-Based Packet Delivery Mode (TSBPD) time conversion logic. +/// Used by the receiver to calculate delivery time of data packets. +/// See SRT Internet Draft Section "Timestamp-Based Packet Delivery". +class CTsbpdTime +{ + typedef srt::sync::steady_clock steady_clock; + typedef steady_clock::time_point time_point; + typedef steady_clock::duration duration; + typedef srt::sync::Mutex Mutex; + +public: + CTsbpdTime() + : m_iFirstRTT(-1) + , m_bTsbPdMode(false) + , m_tdTsbPdDelay(0) + , m_bTsbPdWrapCheck(false) + { + } + + /// Set TimeStamp-Based Packet Delivery Mode (receiver). + /// @param [in] timebase local time base (uSec) of packet time stamps including buffering delay. + /// @param [in] wrap wrapping period. + /// @param [in] delay negotiated TsbPD delay (buffering latency). + void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); + + /// @brief Check if TSBPD logic is enabled. + /// @return true if TSBPD is enabled. + bool isEnabled() const { return m_bTsbPdMode; } + + /// @brief Apply new state derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp wrap period (enabled or not). + /// @param delay TSBPD delay. + /// @param udrift clock drift. + void applyGroupTime(const time_point& timebase, bool wrp, uint32_t delay, const duration& udrift); + + /// @brief Apply new clock state (TSBPD base and drift) derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp state of the wrapping period (enabled or disabled). + /// @param udrift clock drift. + void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift); + + /// @brief Add new drift sample from an ACK-ACKACK pair. + /// ACKACK packets are sent immediately (except for UDP buffering). + /// Therefore their timestamp roughly corresponds to the time of sending + /// and can be used to estimate clock drift. + /// + /// @param [in] pktTimestamp Timestamp of the arrived ACKACK packet. + /// @param [in] tsPktArrival packet arrival time. + /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. If no sample, pass '-1'. + /// + /// @return true if TSBPD base time has changed, false otherwise. + bool addDriftSample(uint32_t pktTimestamp, const time_point& tsPktArrival, int usRTTSample); + + /// @brief Handle timestamp of data packet when 32-bit integer carryover is about to happen. + /// When packet timestamp approaches CPacket::MAX_TIMESTAMP, the TSBPD base time should be + /// shifted accordingly to correctly handle new packets with timestamps starting from zero. + /// @param usPktTimestamp timestamp field value of a data packet. + void updateTsbPdTimeBase(uint32_t usPktTimestamp); + + /// @brief Get TSBPD base time adjusted for carryover, which occurs when + /// a packet's timestamp exceeds the UINT32_MAX and continues from zero. + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return TSBPD base time for a provided packet timestamp. + time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time without buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application. + /// Essentially: getTsbPdTimeBase(usPktTimestamp) + usPktTimestamp + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD base time without buffering delay. + time_point getPktTsbPdBaseTime(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time with buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application + /// (including drift and carryover effects, if any). + /// Essentially: getPktTsbPdBaseTime(usPktTimestamp) + m_tdTsbPdDelay + drift() + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD time with buffering delay. + time_point getPktTsbPdTime(uint32_t usPktTimestamp) const; + + /// @brief Get current drift value. + /// @return current drift value. + int64_t drift() const { return m_DriftTracer.drift(); } + + /// @brief Get current overdrift value. + /// @return current overdrift value. + int64_t overdrift() const { return m_DriftTracer.overdrift(); } + + /// @brief Get internal state to apply to another member of a socket group. + /// @param w_tb TsbPd base time. + /// @param w_udrift drift value. + /// @param w_wrp wrap check. + void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift) const; + +private: + int m_iFirstRTT; // First measured RTT sample. + bool m_bTsbPdMode; // Receiver buffering and TSBPD is active when true. + duration m_tdTsbPdDelay; // Negotiated buffering delay. + + /// @brief Local time base for TsbPd. + /// @note m_tsTsbPdTimeBase is changed in the following cases: + /// 1. Initialized upon SRT_CMD_HSREQ packet as the difference with the current time: + /// = (NOW - PACKET_TIMESTAMP), at the time of HSREQ reception. + /// 2. Shifted forward on timestamp overflow (@see CTsbpdTime::updateTsbPdTimeBase), when overflow + /// of the timestamp field value of a data packet is detected. + /// += CPacket::MAX_TIMESTAMP + 1 + /// 3. Clock drift (@see CTsbpdTime::addDriftSample, executed exclusively + /// from ACKACK handler). This is updated with (positive or negative) TSBPD_DRIFT_MAX_VALUE + /// once the value of average drift exceeds this value in either direction. + /// += (+/-)TSBPD_DRIFT_MAX_VALUE + /// + /// @note The TSBPD base time is expected to hold the following condition: + /// (PACKET_TIMESTAMP + m_tsTsbPdTimeBase + drift) == NOW. + /// Then it can be used to estimate the origin time of a data packet, and calculate its delivery time + /// with buffering delay applied. + time_point m_tsTsbPdTimeBase; + + /// @note Packet timestamps wrap around every 01h11m35s (32-bit in usec). + /// A wrap check period starts 30 seconds (TSBPD_WRAP_PERIOD) before the wrap point. + /// During the wrap check period, packet timestamps smaller than 30 seconds + /// are considered to have been wrapped around. + /// The wrap check period ends 30 seconds after the wrap point, + /// after which the TSBPD base time is adjusted. + bool m_bTsbPdWrapCheck; // true: check packet time stamp wraparound (overflow). + static const uint32_t TSBPD_WRAP_PERIOD = (30 * 1000000); // 30 seconds (in usec) for timestamp wrapping period. + + /// Maximum clock drift (microseconds) above which TsbPD base time is already adjusted. + static const int TSBPD_DRIFT_MAX_VALUE = 5000; + /// Number of samples (ACKACK packets) on which to perform drift calculation and compensation. + static const int TSBPD_DRIFT_MAX_SAMPLES = 1000; + DriftTracer m_DriftTracer; + + /// Protect simultaneous change of state (read/write). + mutable Mutex m_mtxRW; +}; + +} // namespace srt + +#endif // INC_SRT_TSBPD_TIME_H diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/udt.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/udt.h index 77f903bd5..ee4c02f4d 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/udt.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/udt.h @@ -64,16 +64,16 @@ modified by * file doesn't contain _FUNCTIONS_ predicted to be used in C - see udtc.h */ -#ifndef __UDT_H__ -#define __UDT_H__ +#ifndef INC_SRT_UDT_H +#define INC_SRT_UDT_H #include "srt.h" /* -* SRT_ENABLE_THREADCHECK (THIS IS SET IN MAKEFILE NOT HERE) +* SRT_ENABLE_THREADCHECK IS SET IN MAKEFILE, NOT HERE */ #if defined(SRT_ENABLE_THREADCHECK) -#include +#include "threadcheck.h" #else #define THREAD_STATE_INIT(name) #define THREAD_EXIT() @@ -82,13 +82,6 @@ modified by #define INCREMENT_THREAD_ITERATIONS() #endif -/* Obsolete way to define MINGW */ -#ifndef __MINGW__ -#if defined(__MINGW32__) || defined(__MINGW64__) -#define __MINGW__ 1 -#endif -#endif - #ifdef __cplusplus #include #include @@ -96,10 +89,6 @@ modified by #include #endif - -// Legacy/backward/deprecated -#define UDT_API SRT_API - //////////////////////////////////////////////////////////////////////////////// //if compiling on VC6.0 or pre-WindowsXP systems @@ -108,83 +97,6 @@ modified by //if compiling with MinGW, it only works on XP or above //use -D_WIN32_WINNT=0x0501 - -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -// This facility is used only for select() function. -// This is considered obsolete and the epoll() functionality rather should be used. -typedef std::set ud_set; -#define UD_CLR(u, uset) ((uset)->erase(u)) -#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) -#define UD_SET(u, uset) ((uset)->insert(u)) -#define UD_ZERO(uset) ((uset)->clear()) -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Legacy names - -#define UDT_MSS SRTO_MSS -#define UDT_SNDSYN SRTO_SNDSYN -#define UDT_RCVSYN SRTO_RCVSYN -#define UDT_FC SRTO_FC -#define UDT_SNDBUF SRTO_SNDBUF -#define UDT_RCVBUF SRTO_RCVBUF -#define UDT_LINGER SRTO_LINGER -#define UDP_SNDBUF SRTO_UDP_SNDBUF -#define UDP_RCVBUF SRTO_UDP_RCVBUF -#define UDT_MAXMSG SRTO_MAXMSG -#define UDT_MSGTTL SRTO_MSGTTL -#define UDT_RENDEZVOUS SRTO_RENDEZVOUS -#define UDT_SNDTIMEO SRTO_SNDTIMEO -#define UDT_RCVTIMEO SRTO_RCVTIMEO -#define UDT_REUSEADDR SRTO_REUSEADDR -#define UDT_MAXBW SRTO_MAXBW -#define UDT_STATE SRTO_STATE -#define UDT_EVENT SRTO_EVENT -#define UDT_SNDDATA SRTO_SNDDATA -#define UDT_RCVDATA SRTO_RCVDATA -#define SRT_SENDER SRTO_SENDER -#define SRT_TSBPDMODE SRTO_TSBPDMODE -#define SRT_TSBPDDELAY SRTO_TSBPDDELAY -#define SRT_INPUTBW SRTO_INPUTBW -#define SRT_OHEADBW SRTO_OHEADBW -#define SRT_PASSPHRASE SRTO_PASSPHRASE -#define SRT_PBKEYLEN SRTO_PBKEYLEN -#define SRT_KMSTATE SRTO_KMSTATE -#define SRT_IPTTL SRTO_IPTTL -#define SRT_IPTOS SRTO_IPTOS -#define SRT_TLPKTDROP SRTO_TLPKTDROP -#define SRT_TSBPDMAXLAG SRTO_TSBPDMAXLAG -#define SRT_RCVNAKREPORT SRTO_NAKREPORT -#define SRT_CONNTIMEO SRTO_CONNTIMEO -#define SRT_SNDPBKEYLEN SRTO_SNDPBKEYLEN -#define SRT_RCVPBKEYLEN SRTO_RCVPBKEYLEN -#define SRT_SNDPEERKMSTATE SRTO_SNDPEERKMSTATE -#define SRT_RCVKMSTATE SRTO_RCVKMSTATE - -#define UDT_EPOLL_OPT SRT_EPOLL_OPT -#define UDT_EPOLL_IN SRT_EPOLL_IN -#define UDT_EPOLL_OUT SRT_EPOLL_OUT -#define UDT_EPOLL_ERR SRT_EPOLL_ERR - -/* Binary backward compatibility obsolete options */ -#define SRT_NAKREPORT SRT_RCVNAKREPORT - -#if !defined(SRT_DISABLE_LEGACY_UDTSTATUS) -#define UDTSTATUS SRT_SOCKSTATUS -#define INIT SRTS_INIT -#define OPENED SRTS_OPENED -#define LISTENING SRTS_LISTENING -#define CONNECTING SRTS_CONNECTING -#define CONNECTED SRTS_CONNECTED -#define BROKEN SRTS_BROKEN -#define CLOSING SRTS_CLOSING -#define CLOSED SRTS_CLOSED -#define NONEXIST SRTS_NONEXIST -#endif - //////////////////////////////////////////////////////////////////////////////// struct CPerfMon @@ -236,166 +148,75 @@ typedef SRTSOCKET UDTSOCKET; //legacy alias #ifdef __cplusplus -// Class CUDTException exposed for C++ API. -// This is actually useless, unless you'd use a DIRECT C++ API, -// however there's no such API so far. The current C++ API for UDT/SRT -// is predicted to NEVER LET ANY EXCEPTION out of implementation, -// so it's useless to catch this exception anyway. - -class UDT_API CUDTException -{ -public: - - CUDTException(CodeMajor major = MJ_SUCCESS, CodeMinor minor = MN_NONE, int err = -1); - CUDTException(const CUDTException& e); - - ~CUDTException(); - - /// Get the description of the exception. - /// @return Text message for the exception description. - - const char* getErrorMessage(); - - /// Get the system errno for the exception. - /// @return errno. - - int getErrorCode() const; - - /// Get the system network errno for the exception. - /// @return errno. - - int getErrno() const; - /// Clear the error code. - - void clear(); - -private: - CodeMajor m_iMajor; // major exception categories - CodeMinor m_iMinor; // for specific error reasons - int m_iErrno; // errno returned by the system if there is any - std::string m_strMsg; // text error message - - std::string m_strAPI; // the name of UDT function that returns the error - std::string m_strDebug; // debug information, set to the original place that causes the error - -public: // Legacy Error Code - - static const int EUNKNOWN = SRT_EUNKNOWN; - static const int SUCCESS = SRT_SUCCESS; - static const int ECONNSETUP = SRT_ECONNSETUP; - static const int ENOSERVER = SRT_ENOSERVER; - static const int ECONNREJ = SRT_ECONNREJ; - static const int ESOCKFAIL = SRT_ESOCKFAIL; - static const int ESECFAIL = SRT_ESECFAIL; - static const int ECONNFAIL = SRT_ECONNFAIL; - static const int ECONNLOST = SRT_ECONNLOST; - static const int ENOCONN = SRT_ENOCONN; - static const int ERESOURCE = SRT_ERESOURCE; - static const int ETHREAD = SRT_ETHREAD; - static const int ENOBUF = SRT_ENOBUF; - static const int EFILE = SRT_EFILE; - static const int EINVRDOFF = SRT_EINVRDOFF; - static const int ERDPERM = SRT_ERDPERM; - static const int EINVWROFF = SRT_EINVWROFF; - static const int EWRPERM = SRT_EWRPERM; - static const int EINVOP = SRT_EINVOP; - static const int EBOUNDSOCK = SRT_EBOUNDSOCK; - static const int ECONNSOCK = SRT_ECONNSOCK; - static const int EINVPARAM = SRT_EINVPARAM; - static const int EINVSOCK = SRT_EINVSOCK; - static const int EUNBOUNDSOCK = SRT_EUNBOUNDSOCK; - static const int ESTREAMILL = SRT_EINVALMSGAPI; - static const int EDGRAMILL = SRT_EINVALBUFFERAPI; - static const int ENOLISTEN = SRT_ENOLISTEN; - static const int ERDVNOSERV = SRT_ERDVNOSERV; - static const int ERDVUNBOUND = SRT_ERDVUNBOUND; - static const int EINVALMSGAPI = SRT_EINVALMSGAPI; - static const int EINVALBUFFERAPI = SRT_EINVALBUFFERAPI; - static const int EDUPLISTEN = SRT_EDUPLISTEN; - static const int ELARGEMSG = SRT_ELARGEMSG; - static const int EINVPOLLID = SRT_EINVPOLLID; - static const int EASYNCFAIL = SRT_EASYNCFAIL; - static const int EASYNCSND = SRT_EASYNCSND; - static const int EASYNCRCV = SRT_EASYNCRCV; - static const int ETIMEOUT = SRT_ETIMEOUT; - static const int ECONGEST = SRT_ECONGEST; - static const int EPEERERR = SRT_EPEERERR; -}; +namespace srt { class CUDTException; } namespace UDT { -typedef CUDTException ERRORINFO; -//typedef UDT_SOCKOPT SOCKOPT; +typedef srt::CUDTException ERRORINFO; typedef CPerfMon TRACEINFO; -typedef CBytePerfMon TRACEBSTATS; -typedef ud_set UDSET; -UDT_API extern const SRTSOCKET INVALID_SOCK; +// This facility is used only for select() function. +// This is considered obsolete and the epoll() functionality rather should be used. +typedef std::set UDSET; +#define UD_CLR(u, uset) ((uset)->erase(u)) +#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) +#define UD_SET(u, uset) ((uset)->insert(u)) +#define UD_ZERO(uset) ((uset)->clear()) + +SRT_API extern const SRTSOCKET INVALID_SOCK; #undef ERROR -UDT_API extern const int ERROR; - -UDT_API int startup(); -UDT_API int cleanup(); -UDT_API UDTSOCKET socket(int af, int type, int protocol); -UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock); -UDT_API int listen(UDTSOCKET u, int backlog); -UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen); -UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int close(UDTSOCKET u); -UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); -UDT_API int setsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); -UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags); -UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags); - -UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, uint64_t srctime = 0); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len, uint64_t& srctime); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len); - -UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); -UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); +SRT_API extern const int ERROR; + +SRT_API int startup(); +SRT_API int cleanup(); +SRT_API SRTSOCKET socket(); +inline SRTSOCKET socket(int , int , int ) { return socket(); } +SRT_API int bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int bind2(SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int listen(SRTSOCKET u, int backlog); +SRT_API SRTSOCKET accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API int connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int close(SRTSOCKET u); +SRT_API int getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); +SRT_API int setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); +SRT_API int send(SRTSOCKET u, const char* buf, int len, int flags); +SRT_API int recv(SRTSOCKET u, char* buf, int len, int flags); + +SRT_API int sendmsg(SRTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, int64_t srctime = 0); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len, uint64_t& srctime); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len); + +SRT_API int64_t sendfile(SRTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile(SRTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); +SRT_API int64_t sendfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); // select and selectEX are DEPRECATED; please use epoll. -UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); -UDT_API int selectEx(const std::vector& fds, std::vector* readfds, - std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - -UDT_API int epoll_create(); -UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_remove_usock(int eid, UDTSOCKET u); -UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s); -UDT_API int epoll_update_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, +SRT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); +SRT_API int selectEx(const std::vector& fds, std::vector* readfds, + std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); + +SRT_API int epoll_create(); +SRT_API int epoll_add_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_remove_usock(int eid, SRTSOCKET u); +SRT_API int epoll_remove_ssock(int eid, SYSSOCKET s); +SRT_API int epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds = NULL, std::set* wrfds = NULL); -UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut, +SRT_API int epoll_wait2(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL); -UDT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); -UDT_API int epoll_release(int eid); -UDT_API ERRORINFO& getlasterror(); -UDT_API int getlasterror_code(); -UDT_API const char* getlasterror_desc(); -UDT_API int bstats(UDTSOCKET u, TRACEBSTATS* perf, bool clear = true); -UDT_API SRT_SOCKSTATUS getsockstate(UDTSOCKET u); - -// This is a C++ SRT API extension. This is not a part of legacy UDT API. -UDT_API void setloglevel(srt_logging::LogLevel::type ll); -UDT_API void addlogfa(srt_logging::LogFA fa); -UDT_API void dellogfa(srt_logging::LogFA fa); -UDT_API void resetlogfa(std::set fas); -UDT_API void resetlogfa(const int* fara, size_t fara_size); -UDT_API void setlogstream(std::ostream& stream); -UDT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); -UDT_API void setlogflags(int flags); - -UDT_API bool setstreamid(UDTSOCKET u, const std::string& sid); -UDT_API std::string getstreamid(UDTSOCKET u); +SRT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +SRT_API int epoll_release(int eid); +SRT_API ERRORINFO& getlasterror(); +SRT_API int getlasterror_code(); +SRT_API const char* getlasterror_desc(); +SRT_API int bstats(SRTSOCKET u, SRT_TRACEBSTATS* perf, bool clear = true); +SRT_API SRT_SOCKSTATUS getsockstate(SRTSOCKET u); } // namespace UDT @@ -405,7 +226,47 @@ UDT_API std::string getstreamid(UDTSOCKET u); // own logger FA objects, or create their own. The object of this type // is required to initialize the logger FA object. namespace srt_logging { struct LogConfig; } -UDT_API extern srt_logging::LogConfig srt_logger_config; +SRT_API extern srt_logging::LogConfig srt_logger_config; + +namespace srt +{ + +// This is a C++ SRT API extension. This is not a part of legacy UDT API. +SRT_API void setloglevel(srt_logging::LogLevel::type ll); +SRT_API void addlogfa(srt_logging::LogFA fa); +SRT_API void dellogfa(srt_logging::LogFA fa); +SRT_API void resetlogfa(std::set fas); +SRT_API void resetlogfa(const int* fara, size_t fara_size); +SRT_API void setlogstream(std::ostream& stream); +SRT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +SRT_API void setlogflags(int flags); + +SRT_API bool setstreamid(SRTSOCKET u, const std::string& sid); +SRT_API std::string getstreamid(SRTSOCKET u); + +// Namespace alias +namespace logging { + using namespace srt_logging; +} + +} // namespace srt + +// Planned deprecated removal: rel1.6.0 +// There's also no portable way possible to enforce a deprecation +// compiler warning, so leaving as is. +namespace UDT +{ + // Backward-compatible aliases, just for a case someone was using it. + using srt::setloglevel; + using srt::addlogfa; + using srt::dellogfa; + using srt::resetlogfa; + using srt::setlogstream; + using srt::setloghandler; + using srt::setlogflags; + using srt::setstreamid; + using srt::getstreamid; +} #endif /* __cplusplus */ diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/utilities.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/utilities.h new file mode 100644 index 000000000..31e05b205 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/utilities.h @@ -0,0 +1,1098 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_UTILITIES_H +#define INC_SRT_UTILITIES_H + +// Windows warning disabler +#define _CRT_SECURE_NO_WARNINGS 1 + +#include "platform_sys.h" +#include "srt_attr_defs.h" // defines HAVE_CXX11 + +// Happens that these are defined, undefine them in advance +#undef min +#undef max + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_CXX11 +#include +#endif + +#include +#include +#include +#include + +// -------------- UTILITIES ------------------------ + +// --- ENDIAN --- +// Copied from: https://gist.github.com/panzi/6856583 +// License: Public Domain. + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) + +# include + +// GLIBC-2.8 and earlier does not provide these macros. +// See http://linux.die.net/man/3/endian +// From https://gist.github.com/panzi/6856583 +# if defined(__GLIBC__) \ + && ( !defined(__GLIBC_MINOR__) \ + || ((__GLIBC__ < 2) \ + || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) ) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + +# define htole32(x) (x) +# define le32toh(x) (x) + +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) + +# define htole16(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) +# define le16toh(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) + +# define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) +# define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) + +# else +# error Byte Order not supported or not defined. +# endif +# endif + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + +# include + +#ifndef be16toh +# define be16toh(x) betoh16(x) +#endif +#ifndef le16toh +# define le16toh(x) letoh16(x) +#endif + +#ifndef be32toh +# define be32toh(x) betoh32(x) +#endif +#ifndef le32toh +# define le32toh(x) letoh32(x) +#endif + +#ifndef be64toh +# define be64toh(x) betoh64(x) +#endif +#ifndef le64toh +# define le64toh(x) letoh64(x) +#endif + +#elif defined(SUNOS) + + // SunOS/Solaris + + #include + #include + + #define __LITTLE_ENDIAN 1234 + #define __BIG_ENDIAN 4321 + + # if defined(_BIG_ENDIAN) + #define __BYTE_ORDER __BIG_ENDIAN + #define be64toh(x) (x) + #define be32toh(x) (x) + #define be16toh(x) (x) + #define le16toh(x) ((uint16_t)BSWAP_16(x)) + #define le32toh(x) BSWAP_32(x) + #define le64toh(x) BSWAP_64(x) + #define htobe16(x) (x) + #define htole16(x) ((uint16_t)BSWAP_16(x)) + #define htobe32(x) (x) + #define htole32(x) BSWAP_32(x) + #define htobe64(x) (x) + #define htole64(x) BSWAP_64(x) + # else + #define __BYTE_ORDER __LITTLE_ENDIAN + #define be64toh(x) BSWAP_64(x) + #define be32toh(x) ntohl(x) + #define be16toh(x) ntohs(x) + #define le16toh(x) (x) + #define le32toh(x) (x) + #define le64toh(x) (x) + #define htobe16(x) htons(x) + #define htole16(x) (x) + #define htobe32(x) htonl(x) + #define htole32(x) (x) + #define htobe64(x) BSWAP_64(x) + #define htole64(x) (x) + # endif + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error Endian: platform not supported + +#endif + +// Hardware <--> Network (big endian) convention +inline void HtoNLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htonl(src[i]); +} + +inline void NtoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = ntohl(src[i]); +} + +// Hardware <--> Intel (little endian) convention +inline void HtoILA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htole32(src[i]); +} + +inline void ItoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = le32toh(src[i]); +} + +// Bit numbering utility. +// +// This is something that allows you to turn 32-bit integers into bit fields. +// Although bitfields are part of C++ language, they are not designed to be +// interchanged with 32-bit numbers, and any attempt to doing it (by placing +// inside a union, for example) is nonportable (order of bitfields inside +// same-covering 32-bit integer number is dependent on the endian), so they are +// popularly disregarded as useless. Instead the 32-bit numbers with bits +// individually selected is preferred, with usually manual playing around with +// & and | operators, as well as << and >>. This tool is designed to simplify +// the use of them. This can be used to qualify a range of bits inside a 32-bit +// number to be a separate number, you can "wrap" it by placing the integer +// value in the range of these bits, as well as "unwrap" (extract) it from +// the given place. For your own safety, use one prefix to all constants that +// concern bit ranges intended to be inside the same "bit container". +// +// Usage: typedef Bits MASKTYPE; // MASKTYPE is a name of your choice. +// +// With this defined, you can use the following members: +// - MASKTYPE::mask - to get the int32_t value with bimask (used bits set to 1, others to 0) +// - MASKTYPE::offset - to get the lowermost bit number, or number of bits to shift +// - MASKTYPE::wrap(int value) - to create a bitset where given value is encoded in given bits +// - MASKTYPE::unwrap(int bitset) - to extract an integer value from the bitset basing on mask definition +// (rightmost defaults to leftmost) +// REMEMBER: leftmost > rightmost because bit 0 is the LEAST significant one! + +template +struct BitsetMask +{ + static const bool correct = L >= R; + static const uint32_t value = (1u << L) | BitsetMask::value; +}; + +// This is kind-of functional programming. This describes a special case that is +// a "terminal case" in case when decreased L-1 (see above) reached == R. +template +struct BitsetMask +{ + static const bool correct = true; + static const uint32_t value = 1u << R; +}; + +// This is a trap for a case that BitsetMask::correct in the master template definition +// evaluates to false. This trap causes compile error and prevents from continuing +// recursive unwinding in wrong direction (and challenging the compiler's resistiveness +// for infinite loops). +template +struct BitsetMask +{ +}; + +template +struct Bits +{ + // DID YOU GET a kind-of error: 'mask' is not a member of 'Bits<3u, 5u, false>'? + // See the the above declaration of 'correct'! + static const uint32_t mask = BitsetMask::value; + static const uint32_t offset = R; + static const size_t size = L - R + 1; + + // Example: if our bitset mask is 00111100, this checks if given value fits in + // 00001111 mask (that is, does not exceed <0, 15>. + static bool fit(uint32_t value) { return (BitsetMask::value & value) == value; } + + /// 'wrap' gets some given value that should be placed in appropriate bit range and + /// returns a whole 32-bit word that has the value already at specified place. + /// To create a 32-bit container that contains already all values destined for different + /// bit ranges, simply use wrap() for each of them and bind them with | operator. + static uint32_t wrap(uint32_t baseval) { return (baseval << offset) & mask; } + + /// Extracts appropriate bit range and returns them as normal integer value. + static uint32_t unwrap(uint32_t bitset) { return (bitset & mask) >> offset; } + + template + static T unwrapt(uint32_t bitset) { return static_cast(unwrap(bitset)); } +}; + + +//inline int32_t Bit(size_t b) { return 1 << b; } +// XXX This would work only with 'constexpr', but this is +// available only in C++11. In C++03 this can be only done +// using a macro. +// +// Actually this can be expressed in C++11 using a better technique, +// such as user-defined literals: +// 2_bit --> 1 >> 2 + +#ifdef BIT +#undef BIT +#endif +#define BIT(x) (1 << (x)) + + +// ------------------------------------------------------------ +// This is something that reminds a structure consisting of fields +// of the same type, implemented as an array. It's parametrized +// by the type of fields and the type, which's values should be +// used for indexing (preferably an enum type). Whatever type is +// used for indexing, it is converted to size_t for indexing the +// actual array. +// +// The user should use it as an array: ds[DS_NAME], stating +// that DS_NAME is of enum type passed as 3rd parameter. +// However trying to do ds[0] would cause a compile error. +template +struct DynamicStruct +{ + FieldType inarray[NoOfFields]; + + void clear() + { + // As a standard library, it can be believed that this call + // can be optimized when FieldType is some integer. + std::fill(inarray, inarray + NoOfFields, FieldType()); + } + + FieldType operator[](IndexerType ix) const { return inarray[size_t(ix)]; } + FieldType& operator[](IndexerType ix) { return inarray[size_t(ix)]; } + + template + FieldType operator[](AnyOther ix) const + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + template + FieldType& operator[](AnyOther ix) + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + operator FieldType* () { return inarray; } + operator const FieldType* () const { return inarray; } + + char* raw() { return (char*)inarray; } +}; + + +/// Fixed-size array template class. +namespace srt { + +template +class FixedArray +{ +public: + FixedArray(size_t size) + : m_size(size) + , m_entries(new T[size]) + { + } + + ~FixedArray() + { + delete [] m_entries; + } + +public: + const T& operator[](size_t index) const + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](size_t index) + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + const T& operator[](int index) const + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](int index) + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + size_t size() const { return m_size; } + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin() { return m_entries; } + iterator end() { return m_entries + m_size; } + + const_iterator cbegin() const { return m_entries; } + const_iterator cend() const { return m_entries + m_size; } + + T* data() { return m_entries; } + +private: + FixedArray(const FixedArray& ); + FixedArray& operator=(const FixedArray&); + + void raise_expection(int i) const + { + std::stringstream ss; + ss << "Index " << i << "out of range"; + throw std::runtime_error(ss.str()); + } + +private: + size_t m_size; + T* const m_entries; +}; + +} // namespace srt + +// ------------------------------------------------------------ + + + +inline bool IsSet(int32_t bitset, int32_t flagset) +{ + return (bitset & flagset) == flagset; +} + +// std::addressof in C++11, +// needs to be provided for C++03 +template +inline RefType* AddressOf(RefType& r) +{ + return (RefType*)(&(unsigned char&)(r)); +} + +template +struct explicit_t +{ + T inobject; + explicit_t(const T& uo): inobject(uo) {} + + operator T() const { return inobject; } + +private: + template + explicit_t(const X& another); +}; + +// This is required for Printable function if you have a container of pairs, +// but this function has a different definition for C++11 and C++03. +namespace srt_pair_op +{ + template + std::ostream& operator<<(std::ostream& s, const std::pair& v) + { + s << "{" << v.first << " " << v.second << "}"; + return s; + } +} + +#if HAVE_CXX11 + +template +inline auto Move(In& i) -> decltype(std::move(i)) { return std::move(i); } + +// Gluing string of any type, wrapper for operator << + +template +inline Stream& Print(Stream& in) { return in;} + +template +inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args) +{ + sout << arg1; + return Print(sout, args...); +} + +template +inline std::string Sprint(Args&&... args) +{ + std::ostringstream sout; + Print(sout, args...); + return sout.str(); +} + +// We need to use UniquePtr, in the form of C++03 it will be a #define. +// Naturally will be used std::move() so that it can later painlessly +// switch to C++11. +template +using UniquePtr = std::unique_ptr; + +template inline +std::string Printable(const Container& in, Value /*pseudoargument*/, Args&&... args) +{ + using namespace srt_pair_op; + std::ostringstream os; + Print(os, args...); + os << "[ "; + for (auto i: in) + os << Value(i) << " "; + os << "]"; + return os.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + using Value = typename Container::value_type; + return Printable(in, Value()); +} + +template +auto map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) -> typename Map::mapped_type +{ + auto it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +auto map_getp(Map& m, const Key& key) -> typename Map::mapped_type* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + +template +auto map_getp(const Map& m, const Key& key) -> typename Map::mapped_type const* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + + +#else + +// The unique_ptr requires C++11, and the rvalue-reference feature, +// so here we're simulate the behavior using the old std::auto_ptr. + +// This is only to make a "move" call transparent and look ok towards +// the C++11 code. +template +std::auto_ptr_ref Move(const std::auto_ptr_ref& in) { return in; } + +// We need to provide also some fixes for this type that were not present in auto_ptr, +// but they are present in unique_ptr. + +// C++03 doesn't have a templated typedef, but still we need some things +// that can only function as a class. +template +class UniquePtr: public std::auto_ptr +{ + typedef std::auto_ptr Base; + +public: + + // This is a template - so method names must be declared explicitly + typedef typename Base::element_type element_type; + using Base::get; + using Base::reset; + + // All constructor declarations must be repeated. + // "Constructor delegation" is also only C++11 feature. + explicit UniquePtr(element_type* p = 0) throw() : Base(p) {} + UniquePtr(UniquePtr& a) throw() : Base(a) { } + template + UniquePtr(UniquePtr& a) throw() : Base(a) {} + + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + template + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + + // Good, now we need to add some parts of the API of unique_ptr. + + bool operator==(const UniquePtr& two) const { return get() == two.get(); } + bool operator!=(const UniquePtr& two) const { return get() != two.get(); } + + bool operator==(const element_type* two) const { return get() == two; } + bool operator!=(const element_type* two) const { return get() != two; } + + operator bool () { return 0!= get(); } +}; + +// A primitive one-argument versions of Sprint and Printable +template +inline std::string Sprint(const Arg1& arg) +{ + std::ostringstream sout; + sout << arg; + return sout.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator i = in.begin(); i != in.end(); ++i) + os << Value(*i) << " "; + os << "]"; + + return os.str(); +} + +template +typename Map::mapped_type map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type map_get(const Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type* map_getp(Map& m, const Key& key) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +template +typename Map::mapped_type const* map_getp(const Map& m, const Key& key) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +#endif + +// Printable with prefix added for every element. +// Useful when printing a container of sockets or sequence numbers. +template inline +std::string PrintableMod(const Container& in, const std::string& prefix) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator y = in.begin(); y != in.end(); ++y) + os << prefix << Value(*y) << " "; + os << "]"; + return os.str(); +} + +template +inline void FilterIf(InputIterator bg, InputIterator nd, + OutputIterator out, TransFunction fn) +{ + for (InputIterator i = bg; i != nd; ++i) + { + std::pair result = fn(*i); + if (!result.second) + continue; + *out++ = result.first; + } +} + +template +inline void insert_uniq(std::vector& v, const ArgValue& val) +{ + typename std::vector::iterator i = std::find(v.begin(), v.end(), val); + if (i != v.end()) + return; + + v.push_back(val); +} + +template +struct CallbackHolder +{ + void* opaque; + Signature* fn; + + CallbackHolder(): opaque(NULL), fn(NULL) {} + + void set(void* o, Signature* f) + { + // Test if the pointer is a pointer to function. Don't let + // other type of pointers here. +#if HAVE_CXX11 + static_assert(std::is_function::value, "CallbackHolder is for functions only!"); +#else + // This is a poor-man's replacement, which should in most compilers + // generate a warning, if `Signature` resolves to a value type. + // This would make an illegal pointer cast from a value to a function type. + // Casting function-to-function, however, should not. Unfortunately + // newer compilers disallow that, too (when a signature differs), but + // then they should better use the C++11 way, much more reliable and safer. + void* (*testfn)(void*) = (void*(*)(void*))f; + (void)(testfn); +#endif + opaque = o; + fn = f; + } + + operator bool() { return fn != NULL; } +}; + +#define CALLBACK_CALL(holder,...) (*holder.fn)(holder.opaque, __VA_ARGS__) + +inline std::string FormatBinaryString(const uint8_t* bytes, size_t size) +{ + if ( size == 0 ) + return ""; + + //char buf[256]; + using namespace std; + + ostringstream os; + + // I know, it's funny to use sprintf and ostringstream simultaneously, + // but " %02X" in iostream is: << " " << hex << uppercase << setw(2) << setfill('0') << VALUE << setw(1) + // Too noisy. OTOH ostringstream solves the problem of memory allocation + // for a string of unpredictable size. + //sprintf(buf, "%02X", int(bytes[0])); + + os.fill('0'); + os.width(2); + os.setf(ios::basefield, ios::hex); + os.setf(ios::uppercase); + + //os << buf; + os << int(bytes[0]); + + + for (size_t i = 1; i < size; ++i) + { + //sprintf(buf, " %02X", int(bytes[i])); + //os << buf; + os << int(bytes[i]); + } + return os.str(); +} + + +/// This class is useful in every place where +/// the time drift should be traced. It's currently in use in every +/// solution that implements any kind of TSBPD. +template +class DriftTracer +{ + int64_t m_qDrift; + int64_t m_qOverdrift; + + int64_t m_qDriftSum; + unsigned m_uDriftSpan; + +public: + DriftTracer() + : m_qDrift(0) + , m_qOverdrift(0) + , m_qDriftSum(0) + , m_uDriftSpan(0) + {} + + bool update(int64_t driftval) + { + m_qDriftSum += driftval; + ++m_uDriftSpan; + + // I moved it here to calculate accumulated overdrift. + if (CLEAR_ON_UPDATE) + m_qOverdrift = 0; + + if (m_uDriftSpan < MAX_SPAN) + return false; + + + // Calculate the median of all drift values. + // In most cases, the divisor should be == MAX_SPAN. + m_qDrift = m_qDriftSum / m_uDriftSpan; + + // And clear the collection + m_qDriftSum = 0; + m_uDriftSpan = 0; + + // In case of "overdrift", save the overdriven value in 'm_qOverdrift'. + // In clear mode, you should add this value to the time base when update() + // returns true. The drift value will be since now measured with the + // overdrift assumed to be added to the base. + if (std::abs(m_qDrift) > MAX_DRIFT) + { + m_qOverdrift = m_qDrift < 0 ? -MAX_DRIFT : MAX_DRIFT; + m_qDrift -= m_qOverdrift; + } + + // printDriftOffset(m_qOverdrift, m_qDrift); + + // Timebase is separate + // m_qTimeBase += m_qOverdrift; + + return true; + } + + // For group overrides + void forceDrift(int64_t driftval) + { + m_qDrift = driftval; + } + + // These values can be read at any time, however if you want + // to depend on the fact that they have been changed lately, + // you have to check the return value from update(). + // + // IMPORTANT: drift() can be called at any time, just remember + // that this value may look different than before only if the + // last update() returned true, which need not be important for you. + // + // CASE: CLEAR_ON_UPDATE = true + // overdrift() should be read only immediately after update() returned + // true. It will stay available with this value until the next time when + // update() returns true, in which case the value will be cleared. + // Therefore, after calling update() if it retuns true, you should read + // overdrift() immediately an make some use of it. Next valid overdrift + // will be then relative to every previous overdrift. + // + // CASE: CLEAR_ON_UPDATE = false + // overdrift() will start from 0, but it will always keep track on + // any changes in overdrift. By manipulating the MAX_DRIFT parameter + // you can decide how high the drift can go relatively to stay below + // overdrift. + int64_t drift() const { return m_qDrift; } + int64_t overdrift() const { return m_qOverdrift; } +}; + +template +struct MapProxy +{ + std::map& mp; + const KeyType& key; + + MapProxy(std::map& m, const KeyType& k): mp(m), key(k) {} + + void operator=(const ValueType& val) + { + mp[key] = val; + } + + typename std::map::iterator find() + { + return mp.find(key); + } + + typename std::map::const_iterator find() const + { + return mp.find(key); + } + + operator ValueType() const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return ""; + return p->second; + } + + ValueType deflt(const ValueType& defval) const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return defval; + return p->second; + } + + bool exists() const + { + return find() != mp.end(); + } +}; + +/// Print some hash-based stamp of the first 16 bytes in the buffer +inline std::string BufferStamp(const char* mem, size_t size) +{ + using namespace std; + char spread[16]; + + if (size < 16) + memset((spread + size), 0, 16 - size); + memcpy((spread), mem, min(size_t(16), size)); + + // Now prepare 4 cells for uint32_t. + union + { + uint32_t sum; + char cells[4]; + }; + memset((cells), 0, 4); + + for (size_t x = 0; x < 4; ++x) + for (size_t y = 0; y < 4; ++y) + { + cells[x] += spread[x+4*y]; + } + + // Convert to hex string + ostringstream os; + os << hex << uppercase << setfill('0') << setw(8) << sum; + + return os.str(); +} + +template +inline void Split(const std::string & str, char delimiter, OutputIterator tokens) +{ + if ( str.empty() ) + return; // May cause crash and won't extract anything anyway + + std::size_t start; + std::size_t end = -1; + + do + { + start = end + 1; + end = str.find(delimiter, start); + *tokens = str.substr( + start, + (end == std::string::npos) ? std::string::npos : end - start); + ++tokens; + } while (end != std::string::npos); +} + +inline std::string SelectNot(const std::string& unwanted, const std::string& s1, const std::string& s2) +{ + if (s1 == unwanted) + return s2; // might be unwanted, too, but then, there's nothing you can do anyway + if (s2 == unwanted) + return s1; + + // Both have wanted values, so now compare if they are same + if (s1 == s2) + return s1; // occasionally there's a winner + + // Irresolvable situation. + return std::string(); +} + +inline std::string SelectDefault(const std::string& checked, const std::string& def) +{ + if (checked == "") + return def; + return checked; +} + +template +inline size_t safe_advance(It& it, size_t num, It end) +{ + while ( it != end && num ) + { + --num; + ++it; + } + + return num; // will be effectively 0, if reached the required point, or >0, if end was by that number earlier +} + +// This is available only in C++17, dunno why not C++11 as it's pretty useful. +template inline +ATR_CONSTEXPR size_t Size(const V (&)[N]) ATR_NOEXCEPT { return N; } + +template +inline ValueType avg_iir(ValueType old_value, ValueType new_value) +{ + return (old_value * (DEPRLEN - 1) + new_value) / DEPRLEN; +} + +template +inline ValueType avg_iir_w(ValueType old_value, ValueType new_value, size_t new_val_weight) +{ + return (old_value * (DEPRLEN - new_val_weight) + new_value * new_val_weight) / DEPRLEN; +} + +// Property accessor definitions +// +// "Property" is a special method that accesses given field. +// This relies only on a convention, which is the following: +// +// V x = object.prop(); <-- get the property's value +// object.prop(x); <-- set the property a value +// +// Properties might be also chained when setting: +// +// object.prop1(v1).prop2(v2).prop3(v3); +// +// Properties may be defined various even very complicated +// ways, which is simply providing a method with body. In order +// to define a property simplest possible way, that is, refer +// directly to the field that keeps it, here are the following macros: +// +// Prefix: SRTU_PROPERTY_ +// Followed by: +// - access type: RO, WO, RW, RR, RRW +// - chain flag: optional _CHAIN +// Where access type is: +// - RO - read only. Defines reader accessor. The accessor method will be const. +// - RR - read reference. The accessor isn't const to allow reference passthrough. +// - WO - write only. Defines writer accessor. +// - RW - combines RO and WO. +// - RRW - combines RR and WO. +// +// The _CHAIN marker is optional for macros providing writable accessors +// for properties. The difference is that while simple write accessors return +// void, the chaining accessors return the reference to the object for which +// the write accessor was called so that you can call the next accessor (or +// any other method as well) for the result. + +#define SRTU_PROPERTY_RR(type, name, field) type name() { return field; } +#define SRTU_PROPERTY_RO(type, name, field) type name() const { return field; } +#define SRTU_PROPERTY_WO(type, name, field) void set_##name(type arg) { field = arg; } +#define SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) otype& set_##name(type arg) { field = arg; return *this; } +#define SRTU_PROPERTY_RW(type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RRW(type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) +#define SRTU_PROPERTY_RRW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/version.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/version.h index 7033968e8..b2773dd3b 100644 --- a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/version.h +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/version.h @@ -23,10 +23,10 @@ written by #define SRT_VERSION_MAJOR 1 #define SRT_VERSION_MINOR 5 -#define SRT_VERSION_PATCH 1 +#define SRT_VERSION_PATCH 3 /* #undef SRT_VERSION_BUILD */ -#define SRT_VERSION_STRING "1.5.1" +#define SRT_VERSION_STRING "1.5.3" #define SRT_VERSION_VALUE \ SRT_MAKE_VERSION_VALUE( \ SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH ) diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/window.h b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/window.h new file mode 100644 index 000000000..ecc4a4947 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/Headers/window.h @@ -0,0 +1,355 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/22/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_WINDOW_H +#define INC_SRT_WINDOW_H + + +#ifndef _WIN32 + #include + #include +#endif +#include "packet.h" +#include "udt.h" + +namespace srt +{ + +namespace ACKWindowTools +{ + struct Seq + { + int32_t iACKSeqNo; // Seq. No. of the ACK packet + int32_t iACK; // Data packet Seq. No. carried by the ACK packet + sync::steady_clock::time_point tsTimeStamp; // The timestamp when the ACK was sent + }; + + void store(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t ack); + int acknowledge(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime); +} + +template +class CACKWindow +{ +public: + CACKWindow() : + m_aSeq(), + m_iHead(0), + m_iTail(0) + { + m_aSeq[0].iACKSeqNo = SRT_SEQNO_NONE; + } + + ~CACKWindow() {} + + /// Write an ACK record into the window. + /// @param [in] seq Seq. No. of the ACK packet + /// @param [in] ack Data packet Seq. No. carried by the ACK packet + + void store(int32_t seq, int32_t ack) + { + return ACKWindowTools::store(m_aSeq, SIZE, m_iHead, m_iTail, seq, ack); + } + + /// Search the ACKACK "seq" in the window, find out the data packet "ack" + /// and calculate RTT estimate based on the ACK/ACKACK pair + /// @param [in] seq Seq. No. of the ACK packet carried within ACKACK + /// @param [out] ack Acknowledged data packet Seq. No. from the ACK packet that matches the ACKACK + /// @param [in] currtime The timestamp of ACKACK packet reception by the receiver + /// @return RTT + + int acknowledge(int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime) + { + return ACKWindowTools::acknowledge(m_aSeq, SIZE, m_iHead, m_iTail, seq, r_ack, currtime); + } + +private: + + typedef ACKWindowTools::Seq Seq; + + Seq m_aSeq[SIZE]; + int m_iHead; // Pointer to the latest ACK record + int m_iTail; // Pointer to the oldest ACK record + +private: + CACKWindow(const CACKWindow&); + CACKWindow& operator=(const CACKWindow&); +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CPktTimeWindowTools +{ +public: + static int getPktRcvSpeed_in(const int* window, int* replica, const int* bytes, size_t asize, int& bytesps); + static int getBandwidth_in(const int* window, int* replica, size_t psize); + + static void initializeWindowArrays(int* r_pktWindow, int* r_probeWindow, int* r_bytesWindow, size_t asize, size_t psize); +}; + +template +class CPktTimeWindow: CPktTimeWindowTools +{ +public: + CPktTimeWindow(): + m_aPktWindow(), + m_aBytesWindow(), + m_iPktWindowPtr(0), + m_aProbeWindow(), + m_iProbeWindowPtr(0), + m_iLastSentTime(0), + m_iMinPktSndInt(1000000), + m_tsLastArrTime(sync::steady_clock::now()), + m_tsCurrArrTime(), + m_tsProbeTime(), + m_Probe1Sequence(SRT_SEQNO_NONE) + { + // Exception: up to CUDT ctor + sync::setupMutex(m_lockPktWindow, "PktWindow"); + sync::setupMutex(m_lockProbeWindow, "ProbeWindow"); + CPktTimeWindowTools::initializeWindowArrays(m_aPktWindow, m_aProbeWindow, m_aBytesWindow, ASIZE, PSIZE); + } + + ~CPktTimeWindow() + { + } + +public: + /// read the minimum packet sending interval. + /// @return minimum packet sending interval (microseconds). + + int getMinPktSndInt() const { return m_iMinPktSndInt; } + + /// Calculate the packets arrival speed. + /// @return Packet arrival speed (packets per second). + + int getPktRcvSpeed(int& w_bytesps) const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockPktWindow); + + int pktReplica[ASIZE]; // packet information window (inter-packet time) + return getPktRcvSpeed_in(m_aPktWindow, pktReplica, m_aBytesWindow, ASIZE, (w_bytesps)); + } + + int getPktRcvSpeed() const + { + int bytesps; + return getPktRcvSpeed((bytesps)); + } + + /// Estimate the bandwidth. + /// @return Estimated bandwidth (packets per second). + + int getBandwidth() const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + int probeReplica[PSIZE]; + return getBandwidth_in(m_aProbeWindow, probeReplica, PSIZE); + } + + /// Record time information of a packet sending. + /// @param currtime timestamp of the packet sending. + + void onPktSent(int currtime) + { + int interval = currtime - m_iLastSentTime; + + if ((interval < m_iMinPktSndInt) && (interval > 0)) + m_iMinPktSndInt = interval; + + m_iLastSentTime = currtime; + } + + /// Record time information of an arrived packet. + + void onPktArrival(int pktsz = 0) + { + sync::ScopedLock cg(m_lockPktWindow); + + m_tsCurrArrTime = sync::steady_clock::now(); + + // record the packet interval between the current and the last one + m_aPktWindow[m_iPktWindowPtr] = (int) sync::count_microseconds(m_tsCurrArrTime - m_tsLastArrTime); + m_aBytesWindow[m_iPktWindowPtr] = pktsz; + + // the window is logically circular + ++ m_iPktWindowPtr; + if (m_iPktWindowPtr == ASIZE) + m_iPktWindowPtr = 0; + + // remember last packet arrival time + m_tsLastArrTime = m_tsCurrArrTime; + } + + /// Shortcut to test a packet for possible probe 1 or 2 + void probeArrival(const CPacket& pkt, bool unordered) + { + const int inorder16 = pkt.m_iSeqNo & PUMASK_SEQNO_PROBE; + + // for probe1, we want 16th packet + if (inorder16 == 0) + { + probe1Arrival(pkt, unordered); + } + + if (unordered) + return; + + // for probe2, we want 17th packet + if (inorder16 == 1) + { + probe2Arrival(pkt); + } + } + + /// Record the arrival time of the first probing packet. + void probe1Arrival(const CPacket& pkt, bool unordered) + { + if (unordered && pkt.m_iSeqNo == m_Probe1Sequence) + { + // Reset the starting probe into "undefined", when + // a packet has come as retransmitted before the + // measurement at arrival of 17th could be taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + return; + } + + m_tsProbeTime = sync::steady_clock::now(); + m_Probe1Sequence = pkt.m_iSeqNo; // Record the sequence where 16th packet probe was taken + } + + /// Record the arrival time of the second probing packet and the interval between packet pairs. + + void probe2Arrival(const CPacket& pkt) + { + // Reject probes that don't refer to the very next packet + // towards the one that was lately notified by probe1Arrival. + // Otherwise the result can be stupid. + + // Simply, in case when this wasn't called exactly for the + // expected packet pair, behave as if the 17th packet was lost. + + // no start point yet (or was reset) OR not very next packet + if (m_Probe1Sequence == SRT_SEQNO_NONE || CSeqNo::incseq(m_Probe1Sequence) != pkt.m_iSeqNo) + return; + + // Grab the current time before trying to acquire + // a mutex. This might add extra delay and therefore + // screw up the measurement. + const sync::steady_clock::time_point now = sync::steady_clock::now(); + + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + m_tsCurrArrTime = now; + + // Reset the starting probe to prevent checking if the + // measurement was already taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + + // record the probing packets interval + // Adjust the time for what a complete packet would have take + const int64_t timediff = sync::count_microseconds(m_tsCurrArrTime - m_tsProbeTime); + const int64_t timediff_times_pl_size = timediff * CPacket::SRT_MAX_PAYLOAD_SIZE; + + // Let's take it simpler than it is coded here: + // (stating that a packet has never zero size) + // + // probe_case = (now - previous_packet_time) * SRT_MAX_PAYLOAD_SIZE / pktsz; + // + // Meaning: if the packet is fully packed, probe_case = timediff. + // Otherwise the timediff will be "converted" to a time that a fully packed packet "would take", + // provided the arrival time is proportional to the payload size and skipping + // the ETH+IP+UDP+SRT header part elliminates the constant packet delivery time influence. + // + const size_t pktsz = pkt.getLength(); + m_aProbeWindow[m_iProbeWindowPtr] = pktsz ? int(timediff_times_pl_size / pktsz) : int(timediff); + + // OLD CODE BEFORE BSTATS: + // record the probing packets interval + // m_aProbeWindow[m_iProbeWindowPtr] = int(m_tsCurrArrTime - m_tsProbeTime); + + // the window is logically circular + ++ m_iProbeWindowPtr; + if (m_iProbeWindowPtr == PSIZE) + m_iProbeWindowPtr = 0; + } + +private: + int m_aPktWindow[ASIZE]; // Packet information window (inter-packet time) + int m_aBytesWindow[ASIZE]; + int m_iPktWindowPtr; // Position pointer of the packet info. window + mutable sync::Mutex m_lockPktWindow; // Used to synchronize access to the packet window + + int m_aProbeWindow[PSIZE]; // Record inter-packet time for probing packet pairs + int m_iProbeWindowPtr; // Position pointer to the probing window + mutable sync::Mutex m_lockProbeWindow; // Used to synchronize access to the probe window + + int m_iLastSentTime; // Last packet sending time + int m_iMinPktSndInt; // Minimum packet sending interval + + sync::steady_clock::time_point m_tsLastArrTime; // Last packet arrival time + sync::steady_clock::time_point m_tsCurrArrTime; // Current packet arrival time + sync::steady_clock::time_point m_tsProbeTime; // Arrival time of the first probing packet + int32_t m_Probe1Sequence; // Sequence number for which the arrival time was notified + +private: + CPktTimeWindow(const CPktTimeWindow&); + CPktTimeWindow &operator=(const CPktTimeWindow&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/libsrt.a b/Vendor/SRT/libsrt.xcframework/ios-arm64_x86_64-simulator/libsrt.a index af1e7cbd8ba6fa69a46d534ecfd80636e400d629..4ebe52b4738f0fcdce53aad0e25f4ffcb9b0ade1 100644 GIT binary patch delta 971 zcmX}p=f4jG0EO|-b&Y!~qJ$Eqz0i<*Lt5HprJ_ZHdQ?(TQi}AXsL(=Xr=ew}DQ;RM zZ4IH)rh%*$o!=WTzRw?UPQ{W*B^5EEZE;z%=A$OAu3c{sQY4k6SSm{usVdc^L`r2F z*;clb>QY0tmzq*bc90#Vw(KNzq^{JHon;rPFS|+uX(+qN?$Sv1kUeED*<1FJePut{ zUk;E1!qLEApPY=xk(1d&2ozjltFUqECyS) z^_3x|<%8q4Fm8__aYx)4Lt|Ln6?exyF+4`Z$hbG|i~Hk&crZrA=ok|Z#l!JPjE!+I zJ|@J(m=u%a(U=mC#pCfrJQ-8tsdze`iD%=vm=@DxM$C-oV^+KnFUCvpa=a3+#_V`4 z=EU5nh}UCYyb*84Tk&?h6Z2z1yc-MSy;v0Q#|QCYd=wwYC-G@4j?d!r_#(cHCGk}( zjb*VszK(C=+gK6b#rN?;{1`vQ&+$vFj8*Y#{1(5*AF(>t#M<~X*2VhR5F2At{1t!4 pKk;w;7n@_tu+s9P;ZaDXLW&EiTu7BdsuohMXl`kFNl{tf{{ayHaRvYY delta 971 zcmXxh=f4*M0EO|-?KZBiRfHlES&`AYDl>&5ktC9l&?B;vLZqICsI)aHgeW8`rE7-l ztWqkoR5G*2`MvPs`}_gtl&_jmQXZq)6*pfpU-> zEQd&aIaCgl26DI@AxFwl(oh;nV`(ByrA&^NX3|_*$T4!P94E)i338&el#`^Dw3d_Q z6ggGeNLx8gPM3CahP0P6@&5(pk=v^QDViAYJ7`xkxUSOQf4zD&6HW zxm>Q09+LI0l%8^xTrIui8o5@klk4RM=`A-(AGt~TN3A;Op3`dC8ox- zm>&1V{V^kE#sl$SJQTCy;dmq-joI;7JRWmmZafiB##1pbo{stPOgtM4Vqq+b=VEaz ziRWW!l*bG4V!RYD$1Cw_EQ{CT^>`ze$D8q1ydCevyYXJUA1mU6_%J?-kK>bA8LQ&c zSRHHPvsfGJVtsrbU&NR3ReT-a#D>@y-^Qlc99!bM*c#u*5AkFC6hFr=u`Pa$-{SZ9 qBmRuP;_vt;{vBRgRx~mSsZdC9Ar%X$R7mAQsuV3PEh{N%-1|QP^Kha7 diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/access_control.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/access_control.h index 97a1104a8..611e1dad8 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/access_control.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/access_control.h @@ -41,7 +41,7 @@ written by // CODE NOT IN USE 408: unused: no timeout predicted for listener callback #define SRT_REJX_CONFLICT 1409 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only. // CODE NOT IN USE 410: unused: treated as a specific case of 404 -// CODE NOT IN USE 411: unused: no reason to include lenght in the protocol +// CODE NOT IN USE 411: unused: no reason to include length in the protocol // CODE NOT IN USE 412: unused: preconditions not predicted in AC // CODE NOT IN USE 413: unused: AC size is already defined as 512 // CODE NOT IN USE 414: unused: AC size is already defined as 512 diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/api.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/api.h index ca812bf9e..9ba77d23a 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/api.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/api.h @@ -193,6 +193,15 @@ class CUDTSocket /// to finish sending the data that were scheduled for sending so far. void setClosed(); + // This is necessary to be called from the group before the group clears + // the connection with the socket. As for managed groups (and there are + // currently no other group types), a socket disconnected from the group + // is no longer usable. + void setClosing() + { + core().m_bClosing = true; + } + /// This does the same as setClosed, plus sets the m_bBroken to true. /// Such a socket can still be read from so that remaining data from /// the receiver buffer can be read, but no longer sends anything. @@ -447,6 +456,8 @@ class CUDTUnited /// @param cfgSocket socket configuration. /// @return tru if configurations match, false otherwise. static bool channelSettingsMatch(const CSrtMuxerConfig& cfgMuxer, const CSrtConfig& cfgSocket); + static bool inet6SettingsCompat(const sockaddr_any& muxaddr, const CSrtMuxerConfig& cfgMuxer, + const sockaddr_any& reqaddr, const CSrtMuxerConfig& cfgSocket); private: std::map m_mMultiplexer; // UDP multiplexer diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer.h deleted file mode 100644 index 48bcb4311..000000000 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer.h +++ /dev/null @@ -1,611 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2009 -modified by - Haivision Systems Inc. -*****************************************************************************/ - -#ifndef INC_SRT_BUFFER_H -#define INC_SRT_BUFFER_H - -#include "udt.h" -#include "list.h" -#include "queue.h" -#include "tsbpd_time.h" -#include "utilities.h" - -// The notation used for "circular numbers" in comments: -// The "cicrular numbers" are numbers that when increased up to the -// maximum become zero, and similarly, when the zero value is decreased, -// it turns into the maximum value minus one. This wrapping works the -// same for adding and subtracting. Circular numbers cannot be multiplied. - -// Operations done on these numbers are marked with additional % character: -// a %> b : a is later than b -// a ++% (++%a) : shift a by 1 forward -// a +% b : shift a by b -// a == b : equality is same as for just numbers - -namespace srt { - -/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) -class AvgBufSize -{ - typedef sync::steady_clock::time_point time_point; - -public: - AvgBufSize() - : m_dBytesCountMAvg(0.0) - , m_dCountMAvg(0.0) - , m_dTimespanMAvg(0.0) - { - } - -public: - bool isTimeToUpdate(const time_point& now) const; - void update(const time_point& now, int pkts, int bytes, int timespan_ms); - -public: - inline double pkts() const { return m_dCountMAvg; } - inline double timespan_ms() const { return m_dTimespanMAvg; } - inline double bytes() const { return m_dBytesCountMAvg; } - -private: - time_point m_tsLastSamplingTime; - double m_dBytesCountMAvg; - double m_dCountMAvg; - double m_dTimespanMAvg; -}; - -/// The class to estimate source bitrate based on samples submitted to the buffer. -/// Is currently only used by the CSndBuffer. -class CRateEstimator -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; -public: - CRateEstimator(); - -public: - uint64_t getInRatePeriod() const { return m_InRatePeriod; } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_iInRateBps; } - - void setInputRateSmpPeriod(int period); - - /// Update input rate calculation. - /// @param [in] time current time in microseconds - /// @param [in] pkts number of packets newly added to the buffer - /// @param [in] bytes number of payload bytes in those newly added packets - /// - /// @return Current size of the data in the sending list. - void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); - - void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } - -private: // Constants - static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms - static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms - static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload - static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; - -private: - int m_iInRatePktsCount; // number of payload bytes added since InRateStartTime - int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime - time_point m_tsInRateStartTime; - uint64_t m_InRatePeriod; // usec - int m_iInRateBps; // Input Rate in Bytes/sec -}; - -class CSndBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the buffer is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - /// @brief CSndBuffer constructor. - /// @param size initial number of blocks (each block to store one packet payload). - /// @param maxpld maximum packet payload. - CSndBuffer(int size = 32, int maxpld = 1500); - ~CSndBuffer(); - -public: - /// Insert a user buffer into the sending list. - /// For @a w_mctrl the following fields are used: - /// INPUT: - /// - msgttl: timeout for retransmitting the message, if lost - /// - inorder: request to deliver the message in order of sending - /// - srctime: local time as a base for packet's timestamp (0 if unused) - /// - pktseq: sequence number to be stamped on the packet (-1 if unused) - /// - msgno: message number to be stamped on the packet (-1 if unused) - /// OUTPUT: - /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) - /// - pktseq: sequence number to be stamped on the next packet - /// - msgno: message number stamped on the packet - /// @param [in] data pointer to the user data block. - /// @param [in] len size of the block. - /// @param [inout] w_mctrl Message control data - SRT_ATTR_EXCLUDES(m_BufLock) - void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); - - /// Read a block of data from file and insert it into the sending list. - /// @param [in] ifs input file stream. - /// @param [in] len size of the block. - /// @return actual size of data added from the file. - SRT_ATTR_EXCLUDES(m_BufLock) - int addBufferFromFile(std::fstream& ifs, int len); - - /// Find data position to pack a DATA packet from the furthest reading point. - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [in] kflags Odd|Even crypto key flag - /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. - /// @return Actual length of data read. - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); - - /// Peek an information on the next original data packet to send. - /// @return origin time stamp of the next packet; epoch start time otherwise. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point peekNextOriginal() const; - - /// Find data position to pack a DATA packet for a retransmission. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// @param [out] packet the packet to read. - /// @param [out] origintime origin time stamp of the message - /// @param [out] msglen length of the message - /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). - SRT_ATTR_EXCLUDES(m_BufLock) - int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); - - /// Get the time of the last retransmission (if any) of the DATA packet. - /// @param [in] offset offset from the last ACK point (backward sequence number difference) - /// - /// @return Last time of the last retransmission event for the corresponding DATA packet. - SRT_ATTR_EXCLUDES(m_BufLock) - time_point getPacketRexmitTime(const int offset); - - /// Update the ACK point and may release/unmap/return the user data according to the flag. - /// @param [in] offset number of packets acknowledged. - int32_t getMsgNoAt(const int offset); - - void ackData(int offset); - - /// Read size of data still in the sending list. - /// @return Current size of the data in the sending list. - int getCurrBufSize() const; - - SRT_ATTR_EXCLUDES(m_BufLock) - int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); - - void updAvgBufSize(const time_point& time); - int getAvgBufSize(int& bytes, int& timespan); - int getCurrBufSize(int& bytes, int& timespan); - - /// @brief Get the buffering delay of the oldest message in the buffer. - /// @return the delay value. - SRT_ATTR_EXCLUDES(m_BufLock) - duration getBufferingDelay(const time_point& tnow) const; - - uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } - - /// Retrieve input bitrate in bytes per second - int getInputRate() const { return m_rateEstimator.getInputRate(); } - - void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } - - const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } - - void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } - -private: - void increase(); - -private: - mutable sync::Mutex m_BufLock; // used to synchronize buffer operation - - struct Block - { - char* m_pcData; // pointer to the data block - int m_iLength; // payload length of the block. - - int32_t m_iMsgNoBitset; // message number - int32_t m_iSeqNo; // sequence number for scheduling - time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. - time_point m_tsRexmitTime; // packet retransmission time - int m_iTTL; // time to live (milliseconds) - - Block* m_pNext; // next block - - int32_t getMsgSeq() - { - // NOTE: this extracts message ID with regard to REXMIT flag. - // This is valid only for message ID that IS GENERATED in this instance, - // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter - // for the peer that it uses LESS bits to represent the message. - return m_iMsgNoBitset & MSGNO_SEQ::mask; - } - - } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; - - // m_pBlock: The head pointer - // m_pFirstBlock: The first block - // m_pCurrBlock: The current block - // m_pLastBlock: The last block (if first == last, buffer is empty) - - struct Buffer - { - char* m_pcData; // buffer - int m_iSize; // size - Buffer* m_pNext; // next buffer - } * m_pBuffer; // physical buffer - - int32_t m_iNextMsgNo; // next message number - - int m_iSize; // buffer size (number of packets) - const int m_iBlockLen; // maximum length of a block holding packet payload (excluding packet header). - int m_iCount; // number of used blocks - - int m_iBytesCount; // number of payload bytes in queue - time_point m_tsLastOriginTime; - - AvgBufSize m_mavg; - CRateEstimator m_rateEstimator; - -private: - CSndBuffer(const CSndBuffer&); - CSndBuffer& operator=(const CSndBuffer&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -#if (!ENABLE_NEW_RCVBUFFER) - -class CRcvBuffer -{ - typedef sync::steady_clock::time_point time_point; - typedef sync::steady_clock::duration duration; - -public: - // XXX There's currently no way to access the socket ID set for - // whatever the queue is currently working for. Required to find - // some way to do this, possibly by having a "reverse pointer". - // Currently just "unimplemented". - std::string CONID() const { return ""; } - - static const int DEFAULT_SIZE = 65536; - /// Construct the buffer. - /// @param [in] queue CUnitQueue that actually holds the units (packets) - /// @param [in] bufsize_pkts in units (packets) - CRcvBuffer(CUnitQueue* queue, int bufsize_pkts = DEFAULT_SIZE); - ~CRcvBuffer(); - -public: - /// Write data into the buffer. - /// @param [in] unit pointer to a data unit containing new packet - /// @param [in] offset offset from last ACK point. - /// @return 0 is success, -1 if data is repeated. - int addData(CUnit* unit, int offset); - - /// Read data into a user buffer. - /// @param [in] data pointer to user buffer. - /// @param [in] len length of user buffer. - /// @return size of data read. - int readBuffer(char* data, int len); - - /// Read data directly into file. - /// @param [in] file C++ file stream. - /// @param [in] len expected length of data to write into the file. - /// @return size of data read. - int readBufferToFile(std::fstream& ofs, int len); - - /// Update the ACK point of the buffer. - /// @param [in] len number of units to be acknowledged. - /// @return 1 if a user buffer is fulfilled, otherwise 0. - int ackData(int len); - - /// Query how many buffer space left for data receiving. - /// Actually only acknowledged packets, that are still in the buffer, - /// are considered to take buffer space. - /// - /// @return size of available buffer space (including user buffer) for data receiving. - /// Not counting unacknowledged packets. - int getAvailBufSize() const; - - /// Query how many data has been continuously received (for reading) and ready to play (tsbpdtime < now). - /// @return size of valid (continous) data for reading. - int getRcvDataSize() const; - - /// Query how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvDataSize(int& bytes, int& spantime); - - /// Query a 1 sec moving average of how many data was received and acknowledged. - /// @param [out] bytes bytes - /// @param [out] spantime spantime - /// @return size in pkts of acked data. - int getRcvAvgDataSize(int& bytes, int& spantime); - - /// Query how many data of the receive buffer is acknowledged. - /// @param [in] now current time in us. - /// @return none. - void updRcvAvgDataSize(const time_point& now); - - /// Query the received average payload size. - /// @return size (bytes) of payload size - unsigned getRcvAvgPayloadSize() const; - - struct ReadingState - { - time_point tsStart; - time_point tsLastAck; - time_point tsEnd; - int iNumAcknowledged; - int iNumUnacknowledged; - }; - - ReadingState debugGetReadingState() const; - - /// Form a string of the current buffer fullness state. - /// number of packets acknowledged, TSBPD readiness, etc. - std::string strFullnessState(const time_point& tsNow) const; - - /// Mark the message to be dropped from the message list. - /// @param [in] msgno message number. - /// @param [in] using_rexmit_flag whether the MSGNO field uses rexmit flag (if not, one more bit is part of the - /// msgno value) - void dropMsg(int32_t msgno, bool using_rexmit_flag); - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @return actuall size of data read. - int readMsg(char* data, int len); - -#if ENABLE_HEAVY_LOGGING - void readMsgHeavyLogging(int p); -#endif - - /// read a message. - /// @param [out] data buffer to write the message into. - /// @param [in] len size of the buffer. - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// @return actuall size of data read. - int readMsg(char* data, int len, SRT_MSGCTRL& w_mctrl, int upto); - - /// Query if data is ready to read (tsbpdtime <= now if TsbPD is active). - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay - /// of next packet in recv buffer, ready or not. - /// @param [out] curpktseq Sequence number of the packet if there is one ready to play - /// @return true if ready to play, false otherwise (tsbpdtime may be !0 in - /// both cases). - bool isRcvDataReady(time_point& w_tsbpdtime, int32_t& w_curpktseq, int32_t seqdistance); - -#ifdef SRT_DEBUG_TSBPD_OUTJITTER - void debugTraceJitter(time_point t); -#else - void debugTraceJitter(time_point) {} -#endif /* SRT_DEBUG_TSBPD_OUTJITTER */ - - bool isRcvDataReady(); - bool isRcvDataAvailable() { return m_iLastAckPos != m_iStartPos; } - CPacket* getRcvReadyPacket(int32_t seqdistance); - - /// Set TimeStamp-Based Packet Delivery Rx Mode - /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay - /// @param [in] delay aggreed TsbPD delay - void setRcvTsbPdMode(const time_point& timebase, const duration& delay); - - /// Add packet timestamp for drift caclculation and compensation - /// @param [in] timestamp packet time stamp - /// @param [in] tsPktArrival arrival time of the packet used to extract the drift sample. - /// @param [in] rtt RTT sample - bool addRcvTsbPdDriftSample(uint32_t timestamp, const time_point& tsPktArrival, int rtt); - -#ifdef SRT_DEBUG_TSBPD_DRIFT - void printDriftHistogram(int64_t iDrift); - void printDriftOffset(int tsbPdOffset, int tsbPdDriftAvg); -#endif - - /// Get information on the 1st message in queue. - // Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] w_tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 - /// if none - /// @param [out] w_passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] w_skipseqno SRT_SEQNO_NONE or seq number of 1st unacknowledged pkt ready to play preceeded by - /// missing packets. - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base if exist packet ready-to-play - /// and larger than base - /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true - /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != SRT_SEQNO_NONE, packet ready to play preceeded by missing packets.; - /// IF skipseqno == SRT_SEQNO_NONE, no missing packet but 1st not ready to play. - bool getRcvFirstMsg(time_point& w_tsbpdtime, - bool& w_passack, - int32_t& w_skipseqno, - int32_t& w_curpktseq, - int32_t base_seq = SRT_SEQNO_NONE); - - /// Update the ACK point of the buffer. - /// @param [in] len size of data to be skip & acknowledged. - void skipData(int len); - -#if ENABLE_HEAVY_LOGGING - void reportBufferStats() const; // Heavy logging Debug only -#endif - bool empty() const - { - // This will not always return the intended value, - // that is, it may return false when the buffer really is - // empty - but it will return true then in one of next calls. - // This function will be always called again at some point - // if it returned false, and on true the connection - // is going to be broken - so this behavior is acceptable. - return m_iStartPos == m_iLastAckPos; - } - bool full() const { return m_iStartPos == (m_iLastAckPos + 1) % m_iSize; } - int capacity() const { return m_iSize; } - -private: - /// This gives up unit at index p. The unit is given back to the - /// free unit storage for further assignment for the new incoming - /// data. - size_t freeUnitAt(size_t p) - { - CUnit* u = m_pUnit[p]; - m_pUnit[p] = NULL; - size_t rmbytes = u->m_Packet.getLength(); - m_pUnitQueue->makeUnitFree(u); - return rmbytes; - } - - /// Adjust receive queue to 1st ready to play message (tsbpdtime < now). - /// Parameters (of the 1st packet queue, ready to play or not): - /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if - /// none - /// @param base_seq SRT_SEQNO_NONE or desired, ignore seq smaller than base - /// @retval true 1st packet ready to play without discontinuity (no hole) - /// @retval false tsbpdtime = 0: no packet ready to play - bool getRcvReadyMsg(time_point& w_tsbpdtime, int32_t& w_curpktseq, int upto, int base_seq = SRT_SEQNO_NONE); - -public: - /// @brief Get clock drift in microseconds. - int64_t getDrift() const { return m_tsbpd.drift(); } - -public: - int32_t getTopMsgno() const; - - void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift); - - void applyGroupTime(const time_point& timebase, bool wrapcheck, uint32_t delay, const duration& udrift); - void applyGroupDrift(const time_point& timebase, bool wrapcheck, const duration& udrift); - time_point getPktTsbPdTime(uint32_t timestamp); - int debugGetSize() const; - time_point debugGetDeliveryTime(int offset); - - size_t dropData(int len); - -private: - int extractData(char* data, int len, int p, int q, bool passack); - bool accessMsg(int& w_p, int& w_q, bool& w_passack, int64_t& w_playtime, int upto); - - /// Describes the state of the first N packets - std::string debugTimeState(size_t first_n_pkts) const; - - /// thread safe bytes counter of the Recv & Ack buffer - /// @param [in] pkts acked or removed pkts from rcv buffer (used with acked = true) - /// @param [in] bytes number of bytes added/delete (if negative) to/from rcv buffer. - /// @param [in] acked true when adding new pkt in RcvBuffer; false when acking/removing pkts to/from buffer - void countBytes(int pkts, int bytes, bool acked = false); - -private: - bool scanMsg(int& w_start, int& w_end, bool& w_passack); - - int shift(int basepos, int shift) const { return (basepos + shift) % m_iSize; } - - /// Simplified versions with ++ and --; avoid using division instruction - int shiftFwd(int basepos) const - { - if (++basepos == m_iSize) - return 0; - return basepos; - } - - int shiftBack(int basepos) const - { - if (basepos == 0) - return m_iSize - 1; - return --basepos; - } - -private: - CUnit** m_pUnit; // Array of pointed units collected in the buffer - const int m_iSize; // Size of the internal array of CUnit* items - CUnitQueue* m_pUnitQueue; // the shared unit queue - - int m_iStartPos; // HEAD: first packet available for reading - int m_iLastAckPos; // the last ACKed position (exclusive), follows the last readable - // EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1 - int m_iMaxPos; // delta between acked-TAIL and reception-TAIL - - int m_iNotch; // the starting read point of the first unit - // (this is required for stream reading mode; it's - // the position in the first unit in the list - // up to which data are already retrieved; - // in message reading mode it's unused and always 0) - - sync::Mutex m_BytesCountLock; // used to protect counters operations - int m_iBytesCount; // Number of payload bytes in the buffer - int m_iAckedPktsCount; // Number of acknowledged pkts in the buffer - int m_iAckedBytesCount; // Number of acknowledged payload bytes in the buffer - unsigned m_uAvgPayloadSz; // Average payload size for dropped bytes estimation - - CTsbpdTime m_tsbpd; - - AvgBufSize m_mavg; - -private: - CRcvBuffer(); - CRcvBuffer(const CRcvBuffer&); - CRcvBuffer& operator=(const CRcvBuffer&); -}; - -#endif // !ENABLE_NEW_RCVBUFFER - -} // namespace srt - -#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_rcv.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_rcv.h index d628c459f..d4b50fab7 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_rcv.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_rcv.h @@ -11,12 +11,9 @@ #ifndef INC_SRT_BUFFER_RCV_H #define INC_SRT_BUFFER_RCV_H -#if ENABLE_NEW_RCVBUFFER - -#include "buffer.h" // AvgBufSize +#include "buffer_tools.h" // AvgBufSize #include "common.h" #include "queue.h" -#include "sync.h" #include "tsbpd_time.h" namespace srt @@ -26,7 +23,7 @@ namespace srt * Circular receiver buffer. * * |<------------------- m_szSize ---------------------------->| - * | |<------------ m_iMaxPosInc ----------->| | + * | |<------------ m_iMaxPosOff ----------->| | * | | | | * +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+ * | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |...| 0 | m_pUnit[] @@ -45,15 +42,15 @@ namespace srt * first_nonread_pos_: */ -class CRcvBufferNew +class CRcvBuffer { typedef sync::steady_clock::time_point time_point; typedef sync::steady_clock::duration duration; public: - CRcvBufferNew(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); + CRcvBuffer(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI); - ~CRcvBufferNew(); + ~CRcvBuffer(); public: /// Insert a unit into the buffer. @@ -77,14 +74,29 @@ class CRcvBufferNew /// @return the number of dropped packets. int dropAll(); - /// @brief Drop the whole message from the buffer. - /// If message number is 0, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. - /// When one packet of the message is in the range of dropping, the whole message is to be dropped. + enum DropActionIfExists { + DROP_EXISTING = 0, + KEEP_EXISTING = 1 + }; + + /// @brief Drop a sequence of packets from the buffer. + /// If @a msgno is valid, sender has requested to drop the whole message by TTL. In this case it has to also provide a pkt seqno range. + /// However, if a message has been partially acknowledged and already removed from the SND buffer, + /// the @a seqnolo might specify some position in the middle of the message, not the very first packet. + /// If those packets have been acknowledged, they must exist in the receiver buffer unless already read. + /// In this case the @a msgno should be used to determine starting packets of the message. + /// Some packets of the message can be missing on the receiver, therefore the actual drop should still be performed by pkt seqno range. + /// If message number is 0 or SRT_MSGNO_NONE, then use sequence numbers to locate sequence range to drop [seqnolo, seqnohi]. + /// A SOLO message packet can be kept depending on @a actionOnExisting value. + /// TODO: A message in general can be kept if all of its packets are in the buffer, depending on @a actionOnExisting value. + /// This is done to avoid dropping existing packet when the sender was asked to re-transmit a packet from an outdated loss report, + /// which is already not available in the SND buffer. /// @param seqnolo sequence number of the first packet in the dropping range. /// @param seqnohi sequence number of the last packet in the dropping range. /// @param msgno message number to drop (0 if unknown) + /// @param actionOnExisting Should an exising SOLO packet be dropped from the buffer or preserved? /// @return the number of packets actually dropped. - int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno); + int dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno, DropActionIfExists actionOnExisting); /// Read the whole message from one or several packets. /// @@ -130,9 +142,8 @@ class CRcvBufferNew const int iRBufSeqNo = getStartSeqNo(); if (CSeqNo::seqcmp(iRBufSeqNo, iFirstUnackSeqNo) >= 0) // iRBufSeqNo >= iFirstUnackSeqNo { - // Full capacity is available, still don't want to encourage extra packets to come. - // Note: CSeqNo::seqlen(n, n) returns 1. - return capacity() - CSeqNo::seqlen(iFirstUnackSeqNo, iRBufSeqNo) + 1; + // Full capacity is available. + return capacity(); } // Note: CSeqNo::seqlen(n, n) returns 1. @@ -140,13 +151,14 @@ class CRcvBufferNew } /// @brief Checks if the buffer has packets available for reading regardless of the TSBPD. + /// A message is available for reading only if all of its packets are present in the buffer. /// @return true if there are packets available for reading, false otherwise. bool hasAvailablePackets() const; /// Query how many data has been continuously received (for reading) and available for reading out /// regardless of the TSBPD. /// TODO: Rename to countAvailablePackets(). - /// @return size of valid (continous) data for reading. + /// @return size of valid (continuous) data for reading. int getRcvDataSize() const; /// Get the number of packets, bytes and buffer timespan. @@ -165,11 +177,11 @@ class CRcvBufferNew /// Parameters (of the 1st packet queue, ready to play or not): /// @param [out] tsbpdtime localtime-based (uSec) packet time stamp including buffering delay of 1st packet or 0 if /// none - /// @param [out] passack true if 1st ready packet is not yet acknowleged (allowed to be delivered to the app) - /// @param [out] skipseqno -1 or seq number of 1st unacknowledged pkt ready to play preceeded by missing packets. + /// @param [out] passack true if 1st ready packet is not yet acknowledged (allowed to be delivered to the app) + /// @param [out] skipseqno -1 or sequence number of 1st unacknowledged packet (after one or more missing packets) that is ready to play. /// @retval true 1st packet ready to play (tsbpdtime <= now). Not yet acknowledged if passack == true /// @retval false IF tsbpdtime = 0: rcv buffer empty; ELSE: - /// IF skipseqno != -1, packet ready to play preceeded by missing packets.; + /// IF skipseqno != -1, packet ready to play preceded by missing packets.; /// IF skipseqno == -1, no missing packet but 1st not ready to play. PacketInfo getFirstValidPacketInfo() const; @@ -185,7 +197,7 @@ class CRcvBufferNew bool empty() const { - return (m_iMaxPosInc == 0); + return (m_iMaxPosOff == 0); } /// Return buffer capacity. @@ -227,6 +239,18 @@ class CRcvBufferNew inline int incPos(int pos, int inc = 1) const { return (pos + inc) % m_szSize; } inline int decPos(int pos) const { return (pos - 1) >= 0 ? (pos - 1) : int(m_szSize - 1); } inline int offPos(int pos1, int pos2) const { return (pos2 >= pos1) ? (pos2 - pos1) : int(m_szSize + pos2 - pos1); } + inline int cmpPos(int pos2, int pos1) const + { + // XXX maybe not the best implementation, but this keeps up to the rule + const int off1 = pos1 >= m_iStartPos ? pos1 - m_iStartPos : pos1 + (int)m_szSize - m_iStartPos; + const int off2 = pos2 >= m_iStartPos ? pos2 - m_iStartPos : pos2 + (int)m_szSize - m_iStartPos; + + return off2 - off1; + } + + // NOTE: Assumes that pUnit != NULL + CPacket& packetAt(int pos) { return m_entries[pos].pUnit->m_Packet; } + const CPacket& packetAt(int pos) const { return m_entries[pos].pUnit->m_Packet; } private: void countBytes(int pkts, int bytes); @@ -268,7 +292,7 @@ class CRcvBufferNew int getTimespan_ms() const; private: - // TODO: Call makeUnitGood upon assignment, and makeUnitFree upon clearing. + // TODO: Call makeUnitTaken upon assignment, and makeUnitFree upon clearing. // TODO: CUnitPtr is not in use at the moment, but may be a smart pointer. // class CUnitPtr // { @@ -313,7 +337,7 @@ class CRcvBufferNew int m_iStartSeqNo; int m_iStartPos; // the head position for I/O (inclusive) int m_iFirstNonreadPos; // First position that can't be read (<= m_iLastAckPos) - int m_iMaxPosInc; // the furthest data position + int m_iMaxPosOff; // the furthest data position int m_iNotch; // the starting read point of the first unit size_t m_numOutOfOrderPackets; // The number of stored packets with "inorder" flag set to false @@ -326,7 +350,7 @@ class CRcvBufferNew /// Set TimeStamp-Based Packet Delivery Rx Mode /// @param [in] timebase localtime base (uSec) of packet time stamps including buffering delay /// @param [in] wrap Is in wrapping period - /// @param [in] delay aggreed TsbPD delay + /// @param [in] delay agreed TsbPD delay /// /// @return 0 void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); @@ -344,6 +368,8 @@ class CRcvBufferNew time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; void updateTsbPdTimeBase(uint32_t usPktTimestamp); + bool isTsbPd() const { return m_tsbpd.isEnabled(); } + /// Form a string of the current buffer fullness state. /// number of packets acknowledged, TSBPD readiness, etc. std::string strFullnessState(int iFirstUnackSeqNo, const time_point& tsNow) const; @@ -363,5 +389,4 @@ class CRcvBufferNew } // namespace srt -#endif // ENABLE_NEW_RCVBUFFER #endif // INC_SRT_BUFFER_RCV_H diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_snd.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_snd.h new file mode 100644 index 000000000..4440b9bfd --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_snd.h @@ -0,0 +1,259 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_SND_H +#define INC_SRT_BUFFER_SND_H + +#include "srt.h" +#include "packet.h" +#include "buffer_tools.h" + +// The notation used for "circular numbers" in comments: +// The "cicrular numbers" are numbers that when increased up to the +// maximum become zero, and similarly, when the zero value is decreased, +// it turns into the maximum value minus one. This wrapping works the +// same for adding and subtracting. Circular numbers cannot be multiplied. + +// Operations done on these numbers are marked with additional % character: +// a %> b : a is later than b +// a ++% (++%a) : shift a by 1 forward +// a +% b : shift a by b +// a == b : equality is same as for just numbers + +namespace srt { + +class CSndBuffer +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the buffer is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// @brief CSndBuffer constructor. + /// @param size initial number of blocks (each block to store one packet payload). + /// @param maxpld maximum packet payload (including auth tag). + /// @param authtag auth tag length in bytes (16 for GCM, 0 otherwise). + CSndBuffer(int size = 32, int maxpld = 1500, int authtag = 0); + ~CSndBuffer(); + +public: + /// Insert a user buffer into the sending list. + /// For @a w_mctrl the following fields are used: + /// INPUT: + /// - msgttl: timeout for retransmitting the message, if lost + /// - inorder: request to deliver the message in order of sending + /// - srctime: local time as a base for packet's timestamp (0 if unused) + /// - pktseq: sequence number to be stamped on the packet (-1 if unused) + /// - msgno: message number to be stamped on the packet (-1 if unused) + /// OUTPUT: + /// - srctime: local time stamped on the packet (same as input, if input wasn't 0) + /// - pktseq: sequence number to be stamped on the next packet + /// - msgno: message number stamped on the packet + /// @param [in] data pointer to the user data block. + /// @param [in] len size of the block. + /// @param [inout] w_mctrl Message control data + SRT_ATTR_EXCLUDES(m_BufLock) + void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl); + + /// Read a block of data from file and insert it into the sending list. + /// @param [in] ifs input file stream. + /// @param [in] len size of the block. + /// @return actual size of data added from the file. + SRT_ATTR_EXCLUDES(m_BufLock) + int addBufferFromFile(std::fstream& ifs, int len); + + /// Find data position to pack a DATA packet from the furthest reading point. + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [in] kflags Odd|Even crypto key flag + /// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented. + /// @return Actual length of data read. + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc); + + /// Peek an information on the next original data packet to send. + /// @return origin time stamp of the next packet; epoch start time otherwise. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point peekNextOriginal() const; + + /// Find data position to pack a DATA packet for a retransmission. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// @param [out] packet the packet to read. + /// @param [out] origintime origin time stamp of the message + /// @param [out] msglen length of the message + /// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded). + SRT_ATTR_EXCLUDES(m_BufLock) + int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen); + + /// Get the time of the last retransmission (if any) of the DATA packet. + /// @param [in] offset offset from the last ACK point (backward sequence number difference) + /// + /// @return Last time of the last retransmission event for the corresponding DATA packet. + SRT_ATTR_EXCLUDES(m_BufLock) + time_point getPacketRexmitTime(const int offset); + + /// Update the ACK point and may release/unmap/return the user data according to the flag. + /// @param [in] offset number of packets acknowledged. + int32_t getMsgNoAt(const int offset); + + void ackData(int offset); + + /// Read size of data still in the sending list. + /// @return Current size of the data in the sending list. + int getCurrBufSize() const; + + SRT_ATTR_EXCLUDES(m_BufLock) + int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time); + + void updAvgBufSize(const time_point& time); + int getAvgBufSize(int& bytes, int& timespan); + int getCurrBufSize(int& bytes, int& timespan) const; + + + /// Het maximum payload length per packet. + int getMaxPacketLen() const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen) const; + + /// @brief Count the number of required packets to store the payload (message). + /// @param iPldLen the length of the payload to check. + /// @param iMaxPktLen the maximum payload length of the packet (the value returned from getMaxPacketLen()). + /// @return the number of required data packets. + int countNumPacketsRequired(int iPldLen, int iMaxPktLen) const; + + /// @brief Get the buffering delay of the oldest message in the buffer. + /// @return the delay value. + SRT_ATTR_EXCLUDES(m_BufLock) + duration getBufferingDelay(const time_point& tnow) const; + + uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_rateEstimator.getInputRate(); } + + void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); } + + const CRateEstimator& getRateEstimator() const { return m_rateEstimator; } + + void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; } + +private: + void increase(); + +private: + mutable sync::Mutex m_BufLock; // used to synchronize buffer operation + + struct Block + { + char* m_pcData; // pointer to the data block + int m_iLength; // payload length of the block (excluding auth tag). + + int32_t m_iMsgNoBitset; // message number + int32_t m_iSeqNo; // sequence number for scheduling + time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending. + time_point m_tsRexmitTime; // packet retransmission time + int m_iTTL; // time to live (milliseconds) + + Block* m_pNext; // next block + + int32_t getMsgSeq() + { + // NOTE: this extracts message ID with regard to REXMIT flag. + // This is valid only for message ID that IS GENERATED in this instance, + // not provided by the peer. This can be otherwise sent to the peer - it doesn't matter + // for the peer that it uses LESS bits to represent the message. + return m_iMsgNoBitset & MSGNO_SEQ::mask; + } + + } * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; + + // m_pBlock: The head pointer + // m_pFirstBlock: The first block + // m_pCurrBlock: The current block + // m_pLastBlock: The last block (if first == last, buffer is empty) + + struct Buffer + { + char* m_pcData; // buffer + int m_iSize; // size + Buffer* m_pNext; // next buffer + } * m_pBuffer; // physical buffer + + int32_t m_iNextMsgNo; // next message number + + int m_iSize; // buffer size (number of packets) + const int m_iBlockLen; // maximum length of a block holding packet payload and AUTH tag (excluding packet header). + const int m_iAuthTagSize; // Authentication tag size (if GCM is enabled). + int m_iCount; // number of used blocks + + int m_iBytesCount; // number of payload bytes in queue + time_point m_tsLastOriginTime; + + AvgBufSize m_mavg; + CRateEstimator m_rateEstimator; + +private: + CSndBuffer(const CSndBuffer&); + CSndBuffer& operator=(const CSndBuffer&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_tools.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_tools.h new file mode 100644 index 000000000..e6ce89d0d --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/buffer_tools.h @@ -0,0 +1,201 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 05/05/2009 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_BUFFER_TOOLS_H +#define INC_SRT_BUFFER_TOOLS_H + +#include "common.h" + +namespace srt +{ + +/// The AvgBufSize class is used to calculate moving average of the buffer (RCV or SND) +class AvgBufSize +{ + typedef sync::steady_clock::time_point time_point; + +public: + AvgBufSize() + : m_dBytesCountMAvg(0.0) + , m_dCountMAvg(0.0) + , m_dTimespanMAvg(0.0) + { + } + +public: + bool isTimeToUpdate(const time_point& now) const; + void update(const time_point& now, int pkts, int bytes, int timespan_ms); + +public: + inline double pkts() const { return m_dCountMAvg; } + inline double timespan_ms() const { return m_dTimespanMAvg; } + inline double bytes() const { return m_dBytesCountMAvg; } + +private: + time_point m_tsLastSamplingTime; + double m_dBytesCountMAvg; + double m_dCountMAvg; + double m_dTimespanMAvg; +}; + +/// The class to estimate source bitrate based on samples submitted to the buffer. +/// Is currently only used by the CSndBuffer. +class CRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + typedef sync::steady_clock::duration duration; +public: + CRateEstimator(); + +public: + uint64_t getInRatePeriod() const { return m_InRatePeriod; } + + /// Retrieve input bitrate in bytes per second + int getInputRate() const { return m_iInRateBps; } + + void setInputRateSmpPeriod(int period); + + /// Update input rate calculation. + /// @param [in] time current time + /// @param [in] pkts number of packets newly added to the buffer + /// @param [in] bytes number of payload bytes in those newly added packets + void updateInputRate(const time_point& time, int pkts = 0, int bytes = 0); + + void resetInputRateSmpPeriod(bool disable = false) { setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US); } + +private: // Constants + static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms + static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms + static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload + static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE; + +private: + int m_iInRatePktsCount; // number of payload packets added since InRateStartTime. + int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime. + time_point m_tsInRateStartTime; + uint64_t m_InRatePeriod; // usec + int m_iInRateBps; // Input Rate in Bytes/sec +}; + + +class CSndRateEstimator +{ + typedef sync::steady_clock::time_point time_point; + +public: + CSndRateEstimator(const time_point& tsNow); + + /// Add sample. + /// @param [in] time sample (sending) time. + /// @param [in] pkts number of packets in the sample. + /// @param [in] bytes number of payload bytes in the sample. + void addSample(const time_point& time, int pkts = 0, size_t bytes = 0); + + /// Retrieve estimated bitrate in bytes per second + int getRate() const { return m_iRateBps; } + + /// Retrieve estimated bitrate in bytes per second inluding the current sampling interval. + int getCurrentRate() const; + +private: + static const int NUM_PERIODS = 10; + static const int SAMPLE_DURATION_MS = 100; // 100 ms + struct Sample + { + int m_iPktsCount; // number of payload packets + int m_iBytesCount; // number of payload bytes + + void reset() + { + m_iPktsCount = 0; + m_iBytesCount = 0; + } + + Sample() + : m_iPktsCount(0) + , m_iBytesCount(0) + { + } + + Sample(int iPkts, int iBytes) + : m_iPktsCount(iPkts) + , m_iBytesCount(iBytes) + { + } + + Sample operator+(const Sample& other) + { + return Sample(m_iPktsCount + other.m_iPktsCount, m_iBytesCount + other.m_iBytesCount); + } + + Sample& operator+=(const Sample& other) + { + *this = *this + other; + return *this; + } + + bool empty() const { return m_iPktsCount == 0; } + }; + + int incSampleIdx(int val, int inc = 1) const; + + Sample m_Samples[NUM_PERIODS]; + + time_point m_tsFirstSampleTime; //< Start time of the first sameple. + int m_iFirstSampleIdx; //< Index of the first sample. + int m_iCurSampleIdx; //< Index of the current sample being collected. + int m_iRateBps; // Input Rate in Bytes/sec +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/cache.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/cache.h index 0dd57ba01..47633706a 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/cache.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/cache.h @@ -253,7 +253,7 @@ class CInfoBlock CInfoBlock& copyFrom(const CInfoBlock& obj); CInfoBlock(const CInfoBlock& src) { copyFrom(src); } CInfoBlock& operator=(const CInfoBlock& src) { return copyFrom(src); } - bool operator==(const CInfoBlock& obj); + bool operator==(const CInfoBlock& obj) const; CInfoBlock* clone(); int getKey(); void release() {} diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/channel.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/channel.h index 0255102fe..1bfcc47c8 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/channel.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/channel.h @@ -115,9 +115,10 @@ class CChannel /// Send a packet to the given address. /// @param [in] addr pointer to the destination address. /// @param [in] packet reference to a CPacket entity. + /// @param [in] src source address to sent on an outgoing packet (if not ANY) /// @return Actual size of data sent. - int sendto(const sockaddr_any& addr, srt::CPacket& packet) const; + int sendto(const sockaddr_any& addr, srt::CPacket& packet, const sockaddr_any& src) const; /// Receive a packet from the channel and record the source address. /// @param [in] addr pointer to the source address. @@ -128,6 +129,21 @@ class CChannel void setConfig(const CSrtMuxerConfig& config); + void getSocketOption(int level, int sockoptname, char* pw_dataptr, socklen_t& w_len, int& w_status); + + template + Type sockopt(int level, int sockoptname, Type deflt) + { + Type retval; + socklen_t socklen = sizeof retval; + int status; + getSocketOption(level, sockoptname, ((char*)&retval), (socklen), (status)); + if (status == -1) + return deflt; + + return retval; + } + /// Get the IP TTL. /// @param [in] ttl IP Time To Live. /// @return TTL. @@ -160,6 +176,121 @@ class CChannel // although the object itself isn't considered modified. mutable CSrtMuxerConfig m_mcfg; // Note: ReuseAddr is unused and ineffective. sockaddr_any m_BindAddr; + + // This feature is not enabled on Windows, for now. + // This is also turned off in case of MinGW +#ifdef SRT_ENABLE_PKTINFO + bool m_bBindMasked; // True if m_BindAddr is INADDR_ANY. Need for quick check. + + // Calculating the required space is extremely tricky, and whereas on most + // platforms it's possible to define it this way: + // + // size_t s = max( CMSG_SPACE(sizeof(in_pktinfo)), CMSG_SPACE(sizeof(in6_pktinfo)) ) + // + // ...on some platforms however CMSG_SPACE macro can't be resolved as constexpr. + // + // This structure is exclusively used to determine the required size for + // CMSG buffer so that it can be allocated in a solid block with CChannel. + // NOT TO BE USED to access any data inside the CMSG message. + struct CMSGNodeIPv4 + { + in_pktinfo in4; + size_t extrafill; + cmsghdr hdr; + }; + + struct CMSGNodeIPv6 + { + in6_pktinfo in6; + size_t extrafill; + cmsghdr hdr; + }; + + // This is 'mutable' because it's a utility buffer defined here + // to avoid unnecessary re-allocations. + mutable char m_acCmsgRecvBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + mutable char m_acCmsgSendBuffer [sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6)]; // Reserved space for ancillary data with pktinfo + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just after + // calling ::recvmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in receiving mode. + sockaddr_any getTargetAddress(const msghdr& msg) const + { + // Loop through IP header messages + cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(((msghdr*)&msg), cmsg)) + { + // This should be safe - this packet contains always either + // IPv4 headers or IPv6 headers. + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) + { + in_pktinfo *dest_ip_ptr = (in_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi_addr, 0); + } + + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + in6_pktinfo* dest_ip_ptr = (in6_pktinfo*)CMSG_DATA(cmsg); + return sockaddr_any(dest_ip_ptr->ipi6_addr, 0); + } + } + + // Fallback for an error + return sockaddr_any(m_BindAddr.family()); + } + + // IMPORTANT!!! This function shall be called EXCLUSIVELY just before + // calling ::sendmsg function. It uses a static buffer to supply data + // for the call, and it's stated that only one thread is trying to + // use a CChannel object in sending mode. + bool setSourceAddress(msghdr& mh, const sockaddr_any& adr) const + { + // In contrast to an advice followed on the net, there's no case of putting + // both IPv4 and IPv6 ancillary data, case we could have them. Only one + // IP version is used and it's the version as found in @a adr, which should + // be the version used for binding. + + if (adr.family() == AF_INET) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + // after initializing msghdr & control data to CMSG_SPACE(sizeof(struct in_pktinfo)) + cmsg_send->cmsg_level = IPPROTO_IP; + cmsg_send->cmsg_type = IP_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + in_pktinfo* pktinfo = (in_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi_ifindex = 0; + pktinfo->ipi_spec_dst = adr.sin.sin_addr; + + return true; + } + + if (adr.family() == AF_INET6) + { + mh.msg_control = m_acCmsgSendBuffer; + mh.msg_controllen = CMSG_SPACE(sizeof(in6_pktinfo)); + cmsghdr* cmsg_send = CMSG_FIRSTHDR(&mh); + + cmsg_send->cmsg_level = IPPROTO_IPV6; + cmsg_send->cmsg_type = IPV6_PKTINFO; + cmsg_send->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); + in6_pktinfo* pktinfo = (in6_pktinfo*) CMSG_DATA(cmsg_send); + pktinfo->ipi6_ifindex = 0; + pktinfo->ipi6_addr = adr.sin6.sin6_addr; + + return true; + } + + return false; + } + +#endif // SRT_ENABLE_PKTINFO + }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/common.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/common.h index 227a91861..5021fa5a8 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/common.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/common.h @@ -53,7 +53,6 @@ modified by #ifndef INC_SRT_COMMON_H #define INC_SRT_COMMON_H -#define _CRT_SECURE_NO_WARNINGS 1 // silences windows complaints for sscanf #include #include #include @@ -1393,8 +1392,11 @@ inline ATR_CONSTEXPR uint32_t SrtVersion(int major, int minor, int patch) inline int32_t SrtParseVersion(const char* v) { int major, minor, patch; +#if defined(_MSC_VER) + int result = sscanf_s(v, "%d.%d.%d", &major, &minor, &patch); +#else int result = sscanf(v, "%d.%d.%d", &major, &minor, &patch); - +#endif if (result != 3) { return 0; @@ -1409,12 +1411,16 @@ inline std::string SrtVersionString(int version) int minor = (version/0x100)%0x100; int major = version/0x10000; - char buf[20]; - sprintf(buf, "%d.%d.%d", major, minor, patch); + char buf[22]; +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(buf, sizeof(buf) - 1, "%d.%d.%d", major, minor, patch); +#else + snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch); +#endif return buf; } -bool SrtParseConfig(std::string s, SrtConfig& w_config); +bool SrtParseConfig(const std::string& s, SrtConfig& w_config); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/congctl.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/congctl.h index b957dbdd0..a2264b594 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/congctl.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/congctl.h @@ -52,8 +52,8 @@ class SrtCongestion struct IsName { - std::string n; - IsName(std::string nn): n(nn) {} + const std::string n; + IsName(const std::string& nn): n(nn) {} bool operator()(NamePtr np) { return n == np.first; } }; diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/core.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/core.h index fa58ca7c2..71c955c33 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/core.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/core.h @@ -59,7 +59,7 @@ modified by #include "srt.h" #include "common.h" #include "list.h" -#include "buffer.h" +#include "buffer_snd.h" #include "buffer_rcv.h" #include "window.h" #include "packet.h" @@ -288,7 +288,7 @@ class CUDT { #if ENABLE_LOGGING std::ostringstream os; - os << "@" << m_SocketID << ":"; + os << "@" << m_SocketID << ": "; return os.str(); #else return ""; @@ -312,8 +312,10 @@ class CUDT int32_t schedSeqNo() const { return m_iSndNextSeqNo; } bool overrideSndSeqNo(int32_t seq); +#if ENABLE_BONDING sync::steady_clock::time_point lastRspTime() const { return m_tsLastRspTime.load(); } sync::steady_clock::time_point freshActivationStart() const { return m_tsFreshActivation; } +#endif int32_t rcvSeqNo() const { return m_iRcvCurrSeqNo; } int flowWindowSize() const { return m_iFlowWindowSize; } @@ -371,27 +373,34 @@ class CUDT int minSndSize(int len = 0) const { const int ps = (int) maxPayloadSize(); - if (len == 0) // wierd, can't use non-static data member as default argument! + if (len == 0) // weird, can't use non-static data member as default argument! len = ps; return m_config.bMessageAPI ? (len+ps-1)/ps : 1; } - int32_t makeTS(const time_point& from_time) const + static int32_t makeTS(const time_point& from_time, const time_point& tsStartTime) { // NOTE: // - This calculates first the time difference towards start time. // - This difference value is also CUT OFF THE SEGMENT information // (a multiple of MAX_TIMESTAMP+1) // So, this can be simply defined as: TS = (RTS - STS) % (MAX_TIMESTAMP+1) - // XXX Would be nice to check if local_time > m_tsStartTime, - // otherwise it may go unnoticed with clock skew. - return (int32_t) sync::count_microseconds(from_time - m_stats.tsStartTime); + SRT_ASSERT(from_time >= tsStartTime); + return (int32_t) sync::count_microseconds(from_time - tsStartTime); } - void setPacketTS(CPacket& p, const time_point& local_time) - { - p.m_iTimeStamp = makeTS(local_time); - } + /// @brief Set the timestamp field of the packet using the provided value (no check) + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setPacketTS(CPacket& p, const time_point& ts); + + /// @brief Set the timestamp field of the packet according the TSBPD mode. + /// Also checks the connection start time (m_tsStartTime). + /// @param p the packet structure to set the timestamp on. + /// @param ts timestamp to use as a source for packet timestamp. Ignored if m_bPeerTsbPd is false. + SRT_ATTR_EXCLUDES(m_StatsLock) + void setDataPacketTS(CPacket& p, const time_point& ts); // Utility used for closing a listening socket // immediately to free the socket @@ -416,11 +425,7 @@ class CUDT SRTU_PROPERTY_RO(SRTSOCKET, id, m_SocketID); SRTU_PROPERTY_RO(bool, isClosing, m_bClosing); -#if ENABLE_NEW_RCVBUFFER - SRTU_PROPERTY_RO(srt::CRcvBufferNew*, rcvBuffer, m_pRcvBuffer); -#else - SRTU_PROPERTY_RO(CRcvBuffer*, rcvBuffer, m_pRcvBuffer); -#endif + SRTU_PROPERTY_RO(srt::CRcvBuffer*, rcvBuffer, m_pRcvBuffer); SRTU_PROPERTY_RO(bool, isTLPktDrop, m_bTLPktDrop); SRTU_PROPERTY_RO(bool, isSynReceiving, m_config.bSynRecving); SRTU_PROPERTY_RR(sync::Condition*, recvDataCond, &m_RecvDataCond); @@ -441,16 +446,13 @@ class CUDT private: /// initialize a UDT entity and bind to a local address. - void open(); /// Start listening to any connection request. - void setListenState(); /// Connect to a UDT entity listening at address "peer". /// @param peer [in] The address of the listening UDT entity. - void startConnect(const sockaddr_any& peer, int32_t forced_isn); /// Process the response handshake packet. Failure reasons can be: @@ -461,7 +463,6 @@ class CUDT /// @retval 0 Connection successful /// @retval 1 Connection in progress (m_ConnReq turned into RESPONSE) /// @retval -1 Connection failed - SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processConnectResponse(const CPacket& pkt, CUDTException* eout) ATR_NOEXCEPT; @@ -484,15 +485,20 @@ class CUDT /// @param rst Current read status to know if the HS packet was freshly received from the peer, or this is only a periodic update (RST_AGAIN) SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus processRendezvous(const CPacket* response, const sockaddr_any& serv_addr, EReadStatus, CPacket& reqpkt); + void sendRendezvousRejection(const sockaddr_any& serv_addr, CPacket& request); + + /// Create the CryptoControl object based on the HS packet. + SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) + bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException* eout); - /// Create the CryptoControl object based on the HS packet. Allocates sender and receiver buffers and loss lists. + /// Allocates sender and receiver buffers and loss lists. SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) - bool prepareConnectionObjects(const CHandShake &hs, HandshakeSide hsd, CUDTException *eout); + bool prepareBuffers(CUDTException* eout); SRT_ATR_NODISCARD SRT_ATTR_REQUIRES(m_ConnectionLock) EConnectStatus postConnect(const CPacket* response, bool rendezvous, CUDTException* eout) ATR_NOEXCEPT; - SRT_ATR_NODISCARD bool applyResponseSettings() ATR_NOEXCEPT; + SRT_ATR_NODISCARD bool applyResponseSettings(const CPacket* hspkt /*[[nullable]]*/) ATR_NOEXCEPT; SRT_ATR_NODISCARD EConnectStatus processAsyncConnectResponse(const CPacket& pkt) ATR_NOEXCEPT; SRT_ATR_NODISCARD bool processAsyncConnectRequest(EReadStatus rst, EConnectStatus cst, const CPacket* response, const sockaddr_any& serv_addr); SRT_ATR_NODISCARD EConnectStatus craftKmResponse(uint32_t* aw_kmdata, size_t& w_kmdatasize); @@ -662,8 +668,14 @@ class CUDT /// the receiver fresh loss list. void unlose(const CPacket& oldpacket); void dropFromLossLists(int32_t from, int32_t to); + bool getFirstNoncontSequence(int32_t& w_seq, std::string& w_log_reason); + + SRT_ATTR_EXCLUDES(m_ConnectionLock) + void checkSndTimers(); + + /// @brief Check and perform KM refresh if needed. + void checkSndKMRefresh(); - void checkSndTimers(Whether2RegenKm regen = DONT_REGEN_KM); void handshakeDone() { m_iSndHsRetryCnt = 0; @@ -708,18 +720,17 @@ class CUDT SRT_ATTR_EXCLUDES(m_RcvBufferLock) bool isRcvBufferReady() const; + SRT_ATTR_REQUIRES(m_RcvBufferLock) + bool isRcvBufferReadyNoLock() const; + // TSBPD thread main function. static void* tsbpd(void* param); -#if ENABLE_NEW_RCVBUFFER - /// Drop too late packets (receiver side). Updaet loss lists and ACK positions. + /// Drop too late packets (receiver side). Update loss lists and ACK positions. /// The @a seqno packet itself is not dropped. /// @param seqno [in] The sequence number of the first packets following those to be dropped. /// @return The number of packets dropped. int rcvDropTooLateUpTo(int seqno); -#endif - - void updateForgotten(int seqlen, int32_t lastack, int32_t skiptoseqno); static loss_seqs_t defaultPacketArrival(void* vself, CPacket& pkt); static loss_seqs_t groupPacketArrival(void* vself, CPacket& pkt); @@ -811,6 +822,9 @@ class CUDT CSndBuffer* m_pSndBuffer; // Sender buffer CSndLossList* m_pSndLossList; // Sender loss list CPktTimeWindow<16, 16> m_SndTimeWindow; // Packet sending time window +#ifdef ENABLE_MAXREXMITBW + CSndRateEstimator m_SndRexmitRate; // Retransmission rate estimation. +#endif atomic_duration m_tdSendInterval; // Inter-packet time, in CPU clock cycles @@ -826,6 +840,7 @@ class CUDT duration m_tdACKInterval; // ACK interval duration m_tdNAKInterval; // NAK interval + SRT_ATTR_GUARDED_BY(m_RecvAckLock) atomic_time_point m_tsLastRspTime; // Timestamp of last response from the peer time_point m_tsLastRspAckTime; // (SND) Timestamp of last ACK from the peer @@ -851,7 +866,7 @@ class CUDT // and this is the sequence number that refers to the block at position [0]. Upon acknowledgement, // this value is shifted to the acknowledged position, and the blocks are removed from the // m_pSndBuffer buffer up to excluding this sequence number. - // XXX CONSIDER removing this field and give up the maintenance of this sequence number + // XXX CONSIDER removing this field and giving up the maintenance of this sequence number // to the sending buffer. This way, extraction of an old packet for retransmission should // require only the lost sequence number, and how to find the packet with this sequence // will be up to the sending buffer. @@ -894,14 +909,22 @@ class CUDT SRT_ATTR_GUARDED_BY(m_RecvAckLock) int32_t m_iReXmitCount; // Re-Transmit Count since last ACK + time_point m_tsLogSlowDown; // The last time a log message from the "slow down" group was shown. + // The "slow down" group of logs are those that can be printed too often otherwise, but can't be turned off (warnings and errors). + // Currently only used by decryption failure message, therefore no mutex protection needed. + + /// @brief Check if a frequent log can be shown. + /// @param tnow current time + /// @return true if it is ok to print a frequent log message. + bool frequentLogAllowed(const time_point& tnow) const; + private: // Receiving related data -#if ENABLE_NEW_RCVBUFFER - CRcvBufferNew* m_pRcvBuffer; //< Receiver buffer -#else CRcvBuffer* m_pRcvBuffer; //< Receiver buffer -#endif + SRT_ATTR_GUARDED_BY(m_RcvLossLock) CRcvLossList* m_pRcvLossList; //< Receiver loss list + SRT_ATTR_GUARDED_BY(m_RcvLossLock) std::deque m_FreshLoss; //< Lost sequence already added to m_pRcvLossList, but not yet sent UMSG_LOSSREPORT for. + int m_iReorderTolerance; //< Current value of dynamic reorder tolerance int m_iConsecEarlyDelivery; //< Increases with every OOO packet that came m_iRcvCurrSeqNo; // (RCV) Largest received sequence number. RcvQTh, TSBPDTh. int32_t m_iRcvCurrPhySeqNo; // Same as m_iRcvCurrSeqNo, but physical only (disregarding a filter) - + bool m_bBufferWasFull; // Indicate that RX buffer was full last time a ack was sent int32_t m_iPeerISN; // Initial Sequence Number of the peer side uint32_t m_uPeerSrtVersion; @@ -959,7 +981,7 @@ class CUDT mutable sync::Mutex m_RcvBufferLock; // Protects the state of the m_pRcvBuffer // Protects access to m_iSndCurrSeqNo, m_iSndLastAck - sync::Mutex m_RecvAckLock; // Protects the state changes while processing incomming ACK (SRT_EPOLL_OUT) + sync::Mutex m_RecvAckLock; // Protects the state changes while processing incoming ACK (SRT_EPOLL_OUT) sync::Condition m_RecvDataCond; // used to block "srt_recv*" when there is no data. Use together with m_RecvLock sync::Mutex m_RecvLock; // used to synchronize "srt_recv*" call, protects TSBPD drift updates (CRcvBuffer::isRcvDataReady()) @@ -1036,32 +1058,50 @@ class CUDT void updateSndLossListOnACK(int32_t ackdata_seqno); /// Pack a packet from a list of lost packets. - /// /// @param packet [in, out] a packet structure to fill - /// @param origintime [in, out] origin timestamp of the packet - /// /// @return payload size on success, <=0 on failure - int packLostData(CPacket &packet, time_point &origintime); + int packLostData(CPacket &packet); /// Pack a unique data packet (never sent so far) in CPacket for sending. - /// /// @param packet [in, out] a CPacket structure to fill. - /// @param origintime [in, out] origin timestamp of the packet. /// /// @return true if a packet has been packets; false otherwise. - bool packUniqueData(CPacket& packet, time_point& origintime); + bool packUniqueData(CPacket& packet); /// Pack in CPacket the next data to be send. /// - /// @param packet [in, out] a CPacket structure to fill + /// @param packet [out] a CPacket structure to fill + /// @param nexttime [out] Time when this socket should be next time picked up for processing. + /// @param src_addr [out] Source address to pass to channel's sendto /// - /// @return A pair of values is returned (is_payload_valid, timestamp). - /// If is_payload_valid is false, there was nothing packed for sending, - /// and the timestamp value should be ignored. - /// The timestamp is the full source/origin timestamp of the data. - std::pair packData(CPacket& packet); + /// @retval true A packet was extracted for sending, the socket should be rechecked at @a nexttime + /// @retval false Nothing was extracted for sending, @a nexttime should be ignored + bool packData(CPacket& packet, time_point& nexttime, sockaddr_any& src_addr); int processData(CUnit* unit); + + /// This function passes the incoming packet to the initial processing + /// (like packet filter) and is about to store it effectively to the + /// receiver buffer and do some postprocessing (decryption) if necessary + /// and report the status thereof. + /// + /// @param incoming [in] The packet coming from the network medium + /// @param w_new_inserted [out] Set false, if the packet already exists, otherwise true (packet added) + /// @param w_was_sent_in_order [out] Set false, if the packet was belated, but had no R flag set. + /// @param w_srt_loss_seqs [out] Gets inserted a loss, if this function has detected it. + /// + /// @return 0 The call was successful (regardless if the packet was accepted or not). + /// @return -1 The call has failed: no space left in the buffer. + /// @return -2 The incoming packet exceeds the expected sequence by more than a length of the buffer (irrepairable discrepancy). + int handleSocketPacketReception(const std::vector& incoming, bool& w_new_inserted, bool& w_was_sent_in_order, CUDT::loss_seqs_t& w_srt_loss_seqs); + + /// Get the packet's TSBPD time. + /// The @a grp passed by void* is not used yet + /// and shall not be used when ENABLE_BONDING=0. + time_point getPktTsbPdTime(void* grp, const CPacket& packet); + + /// Checks and spawns the TSBPD thread if required. + int checkLazySpawnTsbPdThread(); void processClose(); /// Process the request after receiving the handshake from caller. @@ -1075,12 +1115,7 @@ class CUDT static void addLossRecord(std::vector& lossrecord, int32_t lo, int32_t hi); int32_t bake(const sockaddr_any& addr, int32_t previous_cookie = 0, int correction = 0); - /// @brief Acknowledge reading position up to the @p seq. - /// Updates m_iRcvLastAck and m_iRcvLastSkipAck to @p seq. - /// @param seq first unacknowledged packet sequence number. - void ackDataUpTo(int32_t seq); - -#if ENABLE_BONDING && ENABLE_NEW_RCVBUFFER +#if ENABLE_BONDING /// @brief Drop packets in the recv buffer behind group_recv_base. /// Updates m_iRcvLastSkipAck if it's behind group_recv_base. void dropToGroupRecvBase(); @@ -1088,9 +1123,6 @@ class CUDT void processKeepalive(const CPacket& ctrlpkt, const time_point& tsArrival); - /// Locks m_RcvBufferLock and retrieves the available size of the receiver buffer. - SRT_ATTR_EXCLUDES(m_RcvBufferLock) - size_t getAvailRcvBufferSizeLock() const; /// Retrieves the available size of the receiver buffer. /// Expects that m_RcvBufferLock is locked. @@ -1120,10 +1152,12 @@ class CUDT static const int PACKETPAIR_MASK = 0xF; private: // Timers functions +#if ENABLE_BONDING time_point m_tsFreshActivation; // GROUPS: time of fresh activation of the link, or 0 if past the activation phase or idle time_point m_tsUnstableSince; // GROUPS: time since unexpected ACK delay experienced, or 0 if link seems healthy time_point m_tsWarySince; // GROUPS: time since an unstable link has first some response - +#endif + static const int BECAUSE_NO_REASON = 0, // NO BITS BECAUSE_ACK = 1 << 0, BECAUSE_LITEACK = 1 << 1, @@ -1142,6 +1176,7 @@ class CUDT CSndQueue* m_pSndQueue; // packet sending queue CRcvQueue* m_pRcvQueue; // packet receiving queue sockaddr_any m_PeerAddr; // peer address + sockaddr_any m_SourceAddr; // override UDP source address with this one when sending uint32_t m_piSelfIP[4]; // local UDP IP address CSNode* m_pSNode; // node information for UDT list used in snd queue CRNode* m_pRNode; // node information for UDT list used in rcv queue diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/crypto.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/crypto.h index 2c2b35250..370d5529c 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/crypto.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/crypto.h @@ -50,8 +50,6 @@ const size_t SRT_KMR_KMSTATE = 0; #define SRT_CMD_MAXSZ HCRYPT_MSG_KM_MAX_SZ /* Maximum SRT custom messages payload size (bytes) */ const size_t SRTDATA_MAXSIZE = SRT_CMD_MAXSZ/sizeof(uint32_t); -enum Whether2RegenKm {DONT_REGEN_KM = 0, REGEN_KM = 1}; - class CCryptoControl { SRTSOCKET m_SocketID; @@ -69,10 +67,12 @@ class CCryptoControl // putting the whole HaiCrypt_Cfg object here. int m_KmRefreshRatePkt; int m_KmPreAnnouncePkt; + int m_iCryptoMode; HaiCrypt_Secret m_KmSecret; //Key material shared secret // Sender sync::steady_clock::time_point m_SndKmLastTime; + sync::Mutex m_mtxLock; // A mutex to protect concurrent access to CCryptoControl. struct { unsigned char Msg[HCRYPT_MSG_KM_MAX_SZ]; size_t MsgLen; @@ -87,6 +87,8 @@ class CCryptoControl public: static void globalInit(); + static bool isAESGCMSupported(); + bool sendingAllowed() { // This function is called to state as to whether the @@ -109,15 +111,16 @@ class CCryptoControl return m_KmSecret.len > 0; } -private: -#ifdef SRT_ENABLE_ENCRYPTION - /// Regenerate cryptographic key material. + int getCryptoMode() const + { + return m_iCryptoMode; + } + + /// Regenerate cryptographic key material if needed. /// @param[in] sock If not null, the socket will be used to send the KM message to the peer (e.g. KM refresh). /// @param[in] bidirectional If true, the key material will be regenerated for both directions (receiver and sender). + SRT_ATTR_EXCLUDES(m_mtxLock) void regenCryptoKm(CUDT* sock, bool bidirectional); -#endif - -public: size_t KeyLen() { return m_iSndKmKeyLen; } @@ -205,13 +208,17 @@ class CCryptoControl std::string FormatKmMessage(std::string hdr, int cmd, size_t srtlen); bool init(HandshakeSide, const CSrtConfig&, bool); + SRT_ATTR_EXCLUDES(m_mtxLock) void close(); - /// @return True if the handshake is in progress. + /// (Re)send KM request to a peer on timeout. /// This function is used in: - /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake) - /// - case of key regeneration, which should be then exchanged again. - void sendKeysToPeer(CUDT* sock, int iSRTT, Whether2RegenKm regen); + /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake). + /// - The case of key regeneration (KM refresh), when a new key has to be sent again. + /// In this case the first sending happens in regenCryptoKm(..). This function + /// retransmits the KM request by timeout if not KM response has been received. + SRT_ATTR_EXCLUDES(m_mtxLock) + void sendKeysToPeer(CUDT* sock, int iSRTT); void setCryptoSecret(const HaiCrypt_Secret& secret) { @@ -224,7 +231,7 @@ class CCryptoControl m_iRcvKmKeyLen = keylen; } - bool createCryptoCtx(size_t keylen, HaiCrypt_CryptoDir tx, HaiCrypt_Handle& rh); + bool createCryptoCtx(HaiCrypt_Handle& rh, size_t keylen, HaiCrypt_CryptoDir tx, bool bAESGCM); int getSndCryptoFlags() const { diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/epoll.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/epoll.h index 7b0d941c8..00d46ceb4 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/epoll.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/epoll.h @@ -69,8 +69,11 @@ class CUDTGroup; class CEPollDesc { +#ifdef __GNUG__ const int m_iID; // epoll ID - +#else + const int m_iID SRT_ATR_UNUSED; // epoll ID +#endif struct Wait; struct Notice: public SRT_EPOLL_EVENT diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/fec.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/fec.h index 71a6adfa7..029709475 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/fec.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/fec.h @@ -47,7 +47,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase size_t drop; //< by how much the sequence should increase to get to the next series size_t collected; //< how many packets were taken to collect the clip - Group(): base(CSeqNo::m_iMaxSeqNo), step(0), drop(0), collected(0) + Group(): base(SRT_SEQNO_NONE), step(0), drop(0), collected(0) { } @@ -87,7 +87,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase #if ENABLE_HEAVY_LOGGING std::string DisplayStats() { - if (base == CSeqNo::m_iMaxSeqNo) + if (base == SRT_SEQNO_NONE) return "UNINITIALIZED!!!"; std::ostringstream os; @@ -222,7 +222,7 @@ class FECFilterBuiltin: public SrtPacketFilterBase void RcvRebuild(Group& g, int32_t seqno, Group::Type tp); int32_t RcvGetLossSeqHoriz(Group& g); int32_t RcvGetLossSeqVert(Group& g); - void EmergencyShrink(size_t n_series); + bool CheckEmergencyShrink(size_t n_series, size_t size_in_packets); static void TranslateLossRecords(const std::set& loss, loss_seqs_t& irrecover); void RcvCheckDismissColumn(int32_t seqno, int colgx, loss_seqs_t& irrecover); diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/group.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/group.h index 1bd84aeda..c2863b44e 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/group.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/group.h @@ -155,7 +155,7 @@ class CUDTGroup srt::sync::ScopedLock g(m_GroupLock); bool empty = false; - HLOGC(gmlog.Debug, log << "group/remove: going to remove @" << id << " from $" << m_GroupID); + LOGC(gmlog.Note, log << "group/remove: removing member @" << id << " from group $" << m_GroupID); gli_t f = std::find_if(m_Group.begin(), m_Group.end(), HaveID(id)); if (f != m_Group.end()) @@ -194,9 +194,6 @@ class CUDTGroup m_bConnected = false; } - // XXX BUGFIX - m_Positions.erase(id); - return !empty; } @@ -265,7 +262,7 @@ class CUDTGroup /// @param[in] pktseq Packet sequence number currently tried to be sent /// @param[out] w_u CUDT unit of the current member (to allow calling overrideSndSeqNo) /// @param[out] w_curseq Group's current sequence number (either -1 or the value used already for other links) - /// @param[out] w_final_stat w_final_stat = send_status if sending succeded. + /// @param[out] w_final_stat w_final_stat = send_status if sending succeeded. /// /// @returns true if the sending operation result (submitted in stat) is a success, false otherwise. bool sendBackup_CheckSendStatus(const time_point& currtime, @@ -406,7 +403,9 @@ class CUDTGroup SRTSOCKET m_PeerGroupID; struct GroupContainer { - std::list m_List; + private: + std::list m_List; + sync::atomic m_SizeCache; /// This field is used only by some types of groups that need /// to keep track as to which link was lately used. Note that @@ -414,8 +413,11 @@ class CUDTGroup /// must be appropriately reset. gli_t m_LastActiveLink; + public: + GroupContainer() - : m_LastActiveLink(m_List.end()) + : m_SizeCache(0) + , m_LastActiveLink(m_List.end()) { } @@ -425,18 +427,18 @@ class CUDTGroup gli_t begin() { return m_List.begin(); } gli_t end() { return m_List.end(); } bool empty() { return m_List.empty(); } - void push_back(const SocketData& data) { m_List.push_back(data); } + void push_back(const SocketData& data) { m_List.push_back(data); ++m_SizeCache; } void clear() { m_LastActiveLink = end(); m_List.clear(); + m_SizeCache = 0; } - size_t size() { return m_List.size(); } + size_t size() { return m_SizeCache; } void erase(gli_t it); }; GroupContainer m_Group; - const bool m_bSyncOnMsgNo; // It goes into a dedicated HS field. Could be true for balancing groups (not implemented). SRT_GROUP_TYPE m_type; CUDTSocket* m_listener; // A "group" can only have one listener. srt::sync::atomic m_iBusy; @@ -641,20 +643,6 @@ class CUDTGroup time_point m_tsStartTime; time_point m_tsRcvPeerStartTime; - struct ReadPos - { - std::vector packet; - SRT_MSGCTRL mctrl; - ReadPos(int32_t s) - : mctrl(srt_msgctrl_default) - { - mctrl.pktseq = s; - } - }; - std::map m_Positions; - - ReadPos* checkPacketAhead(); - void recv_CollectAliveAndBroken(std::vector& w_alive, std::set& w_broken); /// The function polls alive member sockets and retrieves a list of read-ready. @@ -813,7 +801,6 @@ class CUDTGroup SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int32_t, currentSchedSequence, m_iLastSchedSeqNo); SRTU_PROPERTY_RRW(std::set&, epollset, m_sPollID); SRTU_PROPERTY_RW_CHAIN(CUDTGroup, int64_t, latency, m_iTsbPdDelay_us); - SRTU_PROPERTY_RO(bool, synconmsgno, m_bSyncOnMsgNo); SRTU_PROPERTY_RO(bool, closing, m_bClosing); }; diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/list.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/list.h index 03f05e927..8f921c698 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/list.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/list.h @@ -53,6 +53,8 @@ modified by #ifndef INC_SRT_LIST_H #define INC_SRT_LIST_H +#include + #include "udt.h" #include "common.h" @@ -84,6 +86,12 @@ class CSndLossList void traceState() const; + // Debug/unittest support. + + int head() const { return m_iHead; } + int next(int loc) const { return m_caSeq[loc].inext; } + int last() const { return m_iLastInsertPos; } + private: struct Seq { @@ -118,6 +126,8 @@ class CSndLossList /// @param seqno2 last sequence number in range (SRT_SEQNO_NONE if no range) bool updateElement(int pos, int32_t seqno1, int32_t seqno2); + static const int LOC_NONE = -1; + private: CSndLossList(const CSndLossList&); CSndLossList& operator=(const CSndLossList&); @@ -134,8 +144,8 @@ class CRcvLossList /// Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. /// @param [in] seqno1 sequence number starts. /// @param [in] seqno2 seqeunce number ends. - - void insert(int32_t seqno1, int32_t seqno2); + /// @return length of the loss record inserted (seqlen(seqno1, seqno2)), -1 on error. + int insert(int32_t seqno1, int32_t seqno2); /// Remove a loss seq. no. from the receiver's loss list. /// @param [in] seqno sequence number. @@ -150,6 +160,12 @@ class CRcvLossList bool remove(int32_t seqno1, int32_t seqno2); + + /// Remove all numbers that precede the given sequence number. + /// @param [in] seqno sequence number. + /// @return the first removed sequence number + int32_t removeUpTo(int32_t seqno); + /// Find if there is any lost packets whose sequence number falling seqno1 and seqno2. /// @param [in] seqno1 start sequence number. /// @param [in] seqno2 end sequence number. @@ -264,6 +280,8 @@ struct CRcvFreshLoss Emod revoke(int32_t sequence); Emod revoke(int32_t lo, int32_t hi); + + static bool removeOne(std::deque& w_container, int32_t sequence, int* had_ttl = NULL); }; } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/logging.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/logging.h index e79785b46..e90ad4ac2 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/logging.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/logging.h @@ -60,6 +60,7 @@ written by // LOGF uses printf-like style formatting. // Usage: LOGF(gglog.Debug, "%s: %d", param1.c_str(), int(param2)); +// NOTE: LOGF is deprecated and should not be used #define LOGF(logdes, ...) if (logdes.CheckEnabled()) logdes().setloc(__FILE__, __LINE__, __FUNCTION__).form(__VA_ARGS__) // LOGP is C++11 only OR with only one string argument. @@ -165,14 +166,24 @@ struct SRT_API LogDispatcher // See Logger::Logger; we know this has normally 2 characters, // except !!FATAL!!, which has 9. Still less than 32. - strcpy(prefix, your_pfx); - // If the size of the FA name together with severity exceeds the size, // just skip the former. if (logger_pfx && strlen(prefix) + strlen(logger_pfx) + 1 < MAX_PREFIX_SIZE) { - strcat(prefix, ":"); - strcat(prefix, logger_pfx); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf(prefix, MAX_PREFIX_SIZE, "%s:%s", your_pfx, logger_pfx); +#else + snprintf(prefix, MAX_PREFIX_SIZE + 1, "%s:%s", your_pfx, logger_pfx); +#endif + } + else + { +#ifdef _MSC_VER + strncpy_s(prefix, MAX_PREFIX_SIZE + 1, your_pfx, _TRUNCATE); +#else + strncpy(prefix, your_pfx, MAX_PREFIX_SIZE); + prefix[MAX_PREFIX_SIZE] = '\0'; +#endif } } @@ -242,7 +253,9 @@ struct SRT_API LogDispatcher return *this; } - DummyProxy& form(const char*, ...) + // DEPRECATED: DO NOT use LOGF/HLOGF macros anymore. + // Use iostream-style formatting with LOGC or a direct argument with LOGP. + SRT_ATR_DEPRECATED_PX DummyProxy& form(const char*, ...) SRT_ATR_DEPRECATED { return *this; } @@ -356,7 +369,11 @@ struct LogDispatcher::Proxy { char buf[512]; - vsprintf(buf, fmts, ap); +#if defined(_MSC_VER) && _MSC_VER < 1900 + _vsnprintf(buf, sizeof(buf) - 1, fmts, ap); +#else + vsnprintf(buf, sizeof(buf), fmts, ap); +#endif size_t len = strlen(buf); if ( buf[len-1] == '\n' ) { diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/md5.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/md5.h index 98bd07665..643981c01 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/md5.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/md5.h @@ -27,7 +27,7 @@ This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at - http://www.ietf.org/rfc/rfc1321.txt + http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being @@ -38,23 +38,24 @@ that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . + added conditionalization for C++ compilation from Martin + Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED -# define md5_INCLUDED +#define md5_INCLUDED /* * All symbols have been put under the srt namespace * to avoid potential linkage conflicts. */ -namespace srt { +namespace srt +{ /* * This package supports both compile-time and run-time determination of CPU @@ -67,23 +68,24 @@ namespace srt { */ typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; /* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); +void md5_init(md5_state_t* pms); /* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +void md5_append(md5_state_t* pms, const md5_byte_t* data, int nbytes); /* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +void md5_finish(md5_state_t* pms, md5_byte_t digest[16]); } // namespace srt diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/netinet_any.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/netinet_any.h new file mode 100644 index 000000000..a38765c08 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/netinet_any.h @@ -0,0 +1,426 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_NETINET_ANY_H +#define INC_SRT_NETINET_ANY_H + +#include // memcmp +#include +#include +#include "platform_sys.h" + +// This structure should replace every use of sockaddr and its currently +// used specializations, sockaddr_in and sockaddr_in6. This is to simplify +// the use of the original BSD API that relies on type-violating type casts. +// You can use the instances of sockaddr_any in every place where sockaddr is +// required. + +namespace srt +{ + +struct sockaddr_any +{ + union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + }; + + // The type is intended to be the same as the length + // parameter in ::accept, ::bind and ::connect functions. + + // This is the type used by SRT. + typedef int len_t; + + // This is the type used by system functions +#ifdef _WIN32 + typedef int syslen_t; +#else + typedef socklen_t syslen_t; +#endif + + // Note: by having `len_t` type here the usage in + // API functions is here limited to SRT. For system + // functions you can pass the address here as (socklen_t*)&sa.len, + // but just do it on your own risk, as there's no guarantee + // that sizes of `int` and `socklen_t` do not differ. The safest + // way seems to be using an intermediate proxy to be written + // back here from the value of `syslen_t`. + len_t len; + + struct SysLenWrapper + { + syslen_t syslen; + len_t& backwriter; + syslen_t* operator&() { return &syslen; } + + SysLenWrapper(len_t& source): syslen(source), backwriter(source) + { + } + + ~SysLenWrapper() + { + backwriter = syslen; + } + }; + + // Usage: + // ::accept(lsn_sock, sa.get(), &sa.syslen()); + SysLenWrapper syslen() + { + return SysLenWrapper(len); + } + + static size_t storage_size() + { + typedef union + { + sockaddr_in sin; + sockaddr_in6 sin6; + sockaddr sa; + } ucopy; + return sizeof (ucopy); + } + + void reset() + { + // sin6 is the largest field + memset((&sin6), 0, sizeof sin6); + len = 0; + } + + // Default domain is unspecified, and + // in this case the size is 0. + // Note that AF_* (and alias PF_*) types have + // many various values, of which only + // AF_INET and AF_INET6 are handled here. + // Others make the same effect as unspecified. + explicit sockaddr_any(int domain = AF_UNSPEC) + { + // Default domain is "unspecified", 0 + reset(); + + // Overriding family as required in the parameters + // and the size then accordingly. + sa.sa_family = domain == AF_INET || domain == AF_INET6 ? domain : AF_UNSPEC; + switch (domain) + { + case AF_INET: + len = len_t(sizeof (sockaddr_in)); + break; + + // Use size of sin6 as the default size + // len must be properly set so that the + // family-less sockaddr is passed to bind/accept + default: + len = len_t(sizeof (sockaddr_in6)); + break; + } + } + + sockaddr_any(const sockaddr_storage& stor) + { + // Here the length isn't passed, so just rely on family. + set((const sockaddr*)&stor); + } + + sockaddr_any(const sockaddr* source, len_t namelen = 0) + { + if (namelen == 0) + set(source); + else + set(source, namelen); + } + + void set(const sockaddr* source) + { + // Less safe version, simply trust the caller that the + // memory at 'source' is also large enough to contain + // all data required for particular family. + if (source->sa_family == AF_INET) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6) + { + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + // Error fallback: no other families than IP are regarded. + // Note: socket set up this way isn't intended to be used + // for bind/accept. + sa.sa_family = AF_UNSPEC; + len = 0; + } + } + + void set(const sockaddr* source, syslen_t namelen) + { + // It's not safe to copy it directly, so check. + if (source->sa_family == AF_INET && namelen >= syslen_t(sizeof sin)) + { + memcpy((&sin), source, sizeof sin); + len = sizeof sin; + } + else if (source->sa_family == AF_INET6 && namelen >= syslen_t(sizeof sin6)) + { + // Note: this isn't too safe, may crash for stupid values + // of source->sa_family or any other data + // in the source structure, so make sure it's correct first. + memcpy((&sin6), source, sizeof sin6); + len = sizeof sin6; + } + else + { + reset(); + } + } + + void set(const sockaddr_in& in4) + { + memcpy((&sin), &in4, sizeof in4); + len = sizeof in4; + } + + void set(const sockaddr_in6& in6) + { + memcpy((&sin6), &in6, sizeof in6); + len = sizeof in6; + } + + sockaddr_any(const in_addr& i4_adr, uint16_t port) + { + // Some cases require separately IPv4 address passed as in_addr, + // so port is given separately. + sa.sa_family = AF_INET; + sin.sin_addr = i4_adr; + sin.sin_port = htons(port); + len = sizeof sin; + } + + sockaddr_any(const in6_addr& i6_adr, uint16_t port) + { + sa.sa_family = AF_INET6; + sin6.sin6_addr = i6_adr; + sin6.sin6_port = htons(port); + len = sizeof sin6; + } + + static len_t size(int family) + { + switch (family) + { + case AF_INET: + return len_t(sizeof (sockaddr_in)); + + case AF_INET6: + return len_t(sizeof (sockaddr_in6)); + + default: + return 0; // fallback + } + } + + bool empty() const + { + bool isempty = true; // unspec-family address is always empty + + if (sa.sa_family == AF_INET) + { + isempty = (sin.sin_port == 0 + && sin.sin_addr.s_addr == 0); + } + else if (sa.sa_family == AF_INET6) + { + isempty = (sin6.sin6_port == 0 + && memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0); + } + // otherwise isempty stays with default false + return isempty; + } + + len_t size() const + { + return size(sa.sa_family); + } + + int family() const { return sa.sa_family; } + void family(int val) + { + sa.sa_family = val; + len = size(); + } + + // port is in exactly the same location in both sin and sin6 + // and has the same size. This is actually yet another common + // field, just not mentioned in the sockaddr structure. + uint16_t& r_port() { return sin.sin_port; } + uint16_t r_port() const { return sin.sin_port; } + int hport() const { return ntohs(sin.sin_port); } + + void hport(int value) + { + // Port is fortunately located at the same position + // in both sockaddr_in and sockaddr_in6 and has the + // same size. + sin.sin_port = htons(value); + } + + sockaddr* get() { return &sa; } + const sockaddr* get() const { return &sa; } + + // Sometimes you need to get the address + // the way suitable for e.g. inet_ntop. + const void* get_addr() const + { + if (sa.sa_family == AF_INET) + return &sin.sin_addr.s_addr; + + if (sa.sa_family == AF_INET6) + return &sin6.sin6_addr; + + return NULL; + } + + void* get_addr() + { + const sockaddr_any* that = this; + return (void*)that->get_addr(); + } + + template struct TypeMap; + + template + typename TypeMap::type& get(); + + struct Equal + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if (c1.family() != c2.family()) + return false; + + // Cannot use memcmp due to having in some systems + // another field like sockaddr_in::sin_len. This exists + // in some BSD-derived systems, but is not required by POSIX. + // Therefore sockaddr_any class cannot operate with it, + // as in this situation it would be safest to state that + // particular implementations may have additional fields + // of different purpose beside those required by POSIX. + // + // The only reliable way to compare two underlying sockaddr + // object is then to compare the port value and the address + // value. + // + // Fortunately the port is 16-bit and located at the same + // offset in both sockaddr_in and sockaddr_in6. + + return c1.sin.sin_port == c2.sin.sin_port + && c1.equal_address(c2); + } + }; + + struct EqualAddress + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + if ( c1.sa.sa_family == AF_INET ) + { + return c1.sin.sin_addr.s_addr == c2.sin.sin_addr.s_addr; + } + + if ( c1.sa.sa_family == AF_INET6 ) + { + return memcmp(&c1.sin6.sin6_addr, &c2.sin6.sin6_addr, sizeof (in6_addr)) == 0; + } + + return false; + } + + }; + + bool equal_address(const sockaddr_any& rhs) const + { + return EqualAddress()(*this, rhs); + } + + struct Less + { + bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) + { + return memcmp(&c1, &c2, sizeof(c1)) < 0; + } + }; + + // Tests if the current address is the "any" wildcard. + bool isany() const + { + if (sa.sa_family == AF_INET) + return sin.sin_addr.s_addr == INADDR_ANY; + + if (sa.sa_family == AF_INET6) + return memcmp(&sin6.sin6_addr, &in6addr_any, sizeof in6addr_any) == 0; + + return false; + } + + // Debug support + std::string str() const + { + if (family() != AF_INET && family() != AF_INET6) + return "unknown:0"; + + std::ostringstream output; + char hostbuf[1024]; + int flags; + + #if ENABLE_GETNAMEINFO + flags = NI_NAMEREQD; + #else + flags = NI_NUMERICHOST | NI_NUMERICSERV; + #endif + + if (!getnameinfo(get(), size(), hostbuf, 1024, NULL, 0, flags)) + { + output << hostbuf; + } + + output << ":" << hport(); + return output.str(); + } + + bool operator==(const sockaddr_any& other) const + { + return Equal()(*this, other); + } + + bool operator!=(const sockaddr_any& other) const { return !(*this == other); } +}; + +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in type; }; +template<> struct sockaddr_any::TypeMap { typedef sockaddr_in6 type; }; + +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin; } +template <> +inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin6; } + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packet.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packet.h new file mode 100644 index 000000000..027d5f0b3 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packet.h @@ -0,0 +1,397 @@ +/* + * SRT - Secure Reliable Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/02/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_PACKET_H +#define INC_SRT_PACKET_H + +#include "udt.h" +#include "common.h" +#include "utilities.h" +#include "netinet_any.h" +#include "packetfilter_api.h" + +namespace srt +{ + +////////////////////////////////////////////////////////////////////////////// +// The purpose of the IOVector class is to proide a platform-independet interface +// to the WSABUF on Windows and iovec on Linux, that can be easilly converted +// to the native structure for use in WSARecvFrom() and recvmsg(...) functions +class IOVector +#ifdef _WIN32 + : public WSABUF +#else + : public iovec +#endif +{ +public: + inline void set(void* buffer, size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; + buf = (CHAR*)buffer; +#else + iov_base = (void*)buffer; + iov_len = length; +#endif + } + + inline char*& dataRef() + { +#ifdef _WIN32 + return buf; +#else + return (char*&)iov_base; +#endif + } + + inline char* data() + { +#ifdef _WIN32 + return buf; +#else + return (char*)iov_base; +#endif + } + + inline size_t size() const + { +#ifdef _WIN32 + return (size_t)len; +#else + return iov_len; +#endif + } + + inline void setLength(size_t length) + { +#ifdef _WIN32 + len = (ULONG)length; +#else + iov_len = length; +#endif + } +}; + +/// To define packets in order in the buffer. This is public due to being used in buffer. +enum PacketBoundary +{ + PB_SUBSEQUENT = 0, // 00: a packet in the middle of a message, neither the first, not the last. + PB_LAST = 1, // 01: last packet of a message + PB_FIRST = 2, // 10: first packet of a message + PB_SOLO = 3, // 11: solo message packet +}; + +// Breakdown of the PM_SEQNO field in the header: +// C| X X ... X, where: +typedef Bits<31> SEQNO_CONTROL; +// 1|T T T T T T T T T T T T T T T|E E...E +typedef Bits<30, 16> SEQNO_MSGTYPE; +typedef Bits<15, 0> SEQNO_EXTTYPE; +// 0|S S ... S +typedef Bits<30, 0> SEQNO_VALUE; + +// This bit cannot be used by SEQNO anyway, so it's additionally used +// in LOSSREPORT data specification to define that this value is the +// BEGIN value for a SEQNO range (to distinguish it from a SOLO loss SEQNO value). +const int32_t LOSSDATA_SEQNO_RANGE_FIRST = SEQNO_CONTROL::mask; + +// Just cosmetics for readability. +const int32_t LOSSDATA_SEQNO_RANGE_LAST = 0, LOSSDATA_SEQNO_SOLO = 0; + +inline int32_t CreateControlSeqNo(UDTMessageType type) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(uint32_t(type)); +} + +inline int32_t CreateControlExtSeqNo(int exttype) +{ + return SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(size_t(UMSG_EXT)) | SEQNO_EXTTYPE::wrap(exttype); +} + +// MSGNO breakdown: B B|O|K K|R|M M M M M M M M M M...M +typedef Bits<31, 30> MSGNO_PACKET_BOUNDARY; +typedef Bits<29> MSGNO_PACKET_INORDER; +typedef Bits<28, 27> MSGNO_ENCKEYSPEC; +#if 1 // can block rexmit flag +// New bit breakdown - rexmit flag supported. +typedef Bits<26> MSGNO_REXMIT; +typedef Bits<25, 0> MSGNO_SEQ; +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ_OLD; +// This symbol is for older SRT version, where the peer does not support the MSGNO_REXMIT flag. +// The message should be extracted as PMASK_MSGNO_SEQ, if REXMIT is supported, and PMASK_MSGNO_SEQ_OLD otherwise. + +const uint32_t PACKET_SND_NORMAL = 0, PACKET_SND_REXMIT = MSGNO_REXMIT::mask; +const int MSGNO_SEQ_MAX = MSGNO_SEQ::mask; + +#else +// Old bit breakdown - no rexmit flag +typedef Bits<26, 0> MSGNO_SEQ; +#endif + +typedef RollNumber MsgNo; + +// constexpr in C++11 ! +inline int32_t PacketBoundaryBits(PacketBoundary o) +{ + return MSGNO_PACKET_BOUNDARY::wrap(int32_t(o)); +} + +enum EncryptionKeySpec +{ + EK_NOENC = 0, + EK_EVEN = 1, + EK_ODD = 2 +}; + +enum EncryptionStatus +{ + ENCS_CLEAR = 0, + ENCS_FAILED = -1, + ENCS_NOTSUP = -2 +}; + +const int32_t PMASK_MSGNO_ENCKEYSPEC = MSGNO_ENCKEYSPEC::mask; +inline int32_t EncryptionKeyBits(EncryptionKeySpec f) +{ + return MSGNO_ENCKEYSPEC::wrap(int32_t(f)); +} +inline EncryptionKeySpec GetEncryptionKeySpec(int32_t msgno) +{ + return EncryptionKeySpec(MSGNO_ENCKEYSPEC::unwrap(msgno)); +} + +const int32_t PUMASK_SEQNO_PROBE = 0xF; + +std::string PacketMessageFlagStr(uint32_t msgno_field); + +class CPacket +{ + friend class CChannel; + friend class CSndQueue; + friend class CRcvQueue; + +public: + CPacket(); + ~CPacket(); + + void allocate(size_t size); + void deallocate(); + + /// Get the payload or the control information field length. + /// @return the payload or the control information field length. + size_t getLength() const; + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + void setLength(size_t len); + + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + /// @param cap [in] capacity (if known). + void setLength(size_t len, size_t cap); + + /// Pack a Control packet. + /// @param pkttype [in] packet type filed. + /// @param lparam [in] pointer to the first data structure, explained by the packet type. + /// @param rparam [in] pointer to the second data structure, explained by the packet type. + /// @param size [in] size of rparam, in number of bytes; + void pack(UDTMessageType pkttype, const int32_t* lparam = NULL, void* rparam = NULL, size_t size = 0); + + /// Read the packet vector. + /// @return Pointer to the packet vector. + IOVector* getPacketVector(); + + uint32_t* getHeader() { return m_nHeader; } + + /// Read the packet type. + /// @return packet type filed (000 ~ 111). + UDTMessageType getType() const; + + bool isControl(UDTMessageType type) const { return isControl() && type == getType(); } + + bool isControl() const { return 0 != SEQNO_CONTROL::unwrap(m_nHeader[SRT_PH_SEQNO]); } + + void setControl(UDTMessageType type) { m_nHeader[SRT_PH_SEQNO] = SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(type); } + + /// Read the extended packet type. + /// @return extended packet type filed (0x000 ~ 0xFFF). + int getExtendedType() const; + + /// Read the ACK-2 seq. no. + /// @return packet header field (bit 16~31). + int32_t getAckSeqNo() const; + + uint16_t getControlFlags() const; + + // Note: this will return a "singular" value, if the packet + // contains the control message + int32_t getSeqNo() const { return m_nHeader[SRT_PH_SEQNO]; } + + /// Read the message boundary flag bit. + /// @return packet header field [1] (bit 0~1). + PacketBoundary getMsgBoundary() const; + + /// Read the message inorder delivery flag bit. + /// @return packet header field [1] (bit 2). + bool getMsgOrderFlag() const; + + /// Read the rexmit flag (true if the packet was sent due to retransmission). + /// If the peer does not support retransmission flag, the current agent cannot use it as well + /// (because the peer will understand this bit as a part of MSGNO field). + bool getRexmitFlag() const; + + void setRexmitFlag(bool bRexmit); + + /// Read the message sequence number. + /// @return packet header field [1] + int32_t getMsgSeq(bool has_rexmit = true) const; + + /// Read the message crypto key bits. + /// @return packet header field [1] (bit 3~4). + EncryptionKeySpec getMsgCryptoFlags() const; + + void setMsgCryptoFlags(EncryptionKeySpec spec); + + /// Read the message time stamp. + /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). + uint32_t getMsgTimeStamp() const; + + sockaddr_any udpDestAddr() const { return m_DestAddr; } + +#ifdef SRT_DEBUG_TSBPD_WRAP // Receiver + static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; // 27 bit fast wraparound for tests (~2m15s) +#else + static const uint32_t MAX_TIMESTAMP = 0xFFFFFFFF; // Full 32 bit (01h11m35s) +#endif + +protected: + static const uint32_t TIMESTAMP_MASK = MAX_TIMESTAMP; // this value to be also used as a mask +public: + /// Clone this packet. + /// @return Pointer to the new packet. + CPacket* clone() const; + + enum PacketVectorFields + { + PV_HEADER = 0, + PV_DATA = 1, + + PV_SIZE = 2 + }; + +public: + void toNL(); + void toHL(); + +protected: + // DynamicStruct is the same as array of given type and size, just it + // enforces that you index it using a symbol from symbolic enum type, not by a bare integer. + typedef DynamicStruct HEADER_TYPE; + HEADER_TYPE m_nHeader; //< The 128-bit header field + + IOVector m_PacketVector[PV_SIZE]; //< The two-dimensional vector of an SRT packet [header, data] + + int32_t m_extra_pad; + bool m_data_owned; + sockaddr_any m_DestAddr; + size_t m_zCapacity; + +protected: + CPacket& operator=(const CPacket&); + CPacket(const CPacket&); + +public: + int32_t& m_iSeqNo; // alias: sequence number + int32_t& m_iMsgNo; // alias: message number + int32_t& m_iTimeStamp; // alias: timestamp + int32_t& m_iID; // alias: destination SRT socket ID + char*& m_pcData; // alias: payload (data packet) / control information fields (control packet) + + // Experimental: sometimes these references don't work! + char* getData(); + char* release(); + + static const size_t HDR_SIZE = sizeof(HEADER_TYPE); // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t) + + // Can also be calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr). + static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }. + + static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE; + + // Maximum transmission unit size. 1500 in case of Ethernet II (RFC 1191). + static const size_t ETH_MAX_MTU_SIZE = 1500; + + // Maximum payload size of an SRT packet. + static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE; + + // Packet interface + char* data() { return m_pcData; } + const char* data() const { return m_pcData; } + size_t size() const { return getLength(); } + size_t capacity() const { return m_zCapacity; } + void setCapacity(size_t cap) { m_zCapacity = cap; } + uint32_t header(SrtPktHeaderFields field) const { return m_nHeader[field]; } + +#if ENABLE_LOGGING + std::string MessageFlagStr() { return PacketMessageFlagStr(m_nHeader[SRT_PH_MSGNO]); } + std::string Info(); +#else + std::string MessageFlagStr() { return std::string(); } + std::string Info() { return std::string(); } +#endif +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter.h new file mode 100644 index 000000000..429e81e79 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter.h @@ -0,0 +1,219 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_H +#define INC_SRT_PACKETFILTER_H + +#include +#include +#include + +#include "packet.h" +#include "utilities.h" +#include "packetfilter_api.h" + +namespace srt { + +class CUnitQueue; +struct CUnit; +class CUDT; + +class PacketFilter +{ + friend class SrtPacketFilterBase; + +public: + typedef std::vector< std::pair > loss_seqs_t; + + typedef SrtPacketFilterBase* filter_create_t(const SrtFilterInitializer& init, std::vector&, const std::string& config); + + class Factory + { + public: + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, std::vector& provided, const std::string& confstr) = 0; + + // Characteristic data + virtual size_t ExtraSize() const = 0; + + // Represent default parameters. This is for completing and comparing + // filter configurations from both parties. Possible values to return: + // - an empty string (all parameters are mandatory) + // - a form of: ",:,..." + virtual std::string defaultConfig() const = 0; + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const = 0; + virtual ~Factory(); + }; +private: + friend bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + + template + class Creator: public Factory + { + virtual SrtPacketFilterBase* Create(const SrtFilterInitializer& init, + std::vector& provided, + const std::string& confstr) ATR_OVERRIDE + { return new Target(init, provided, confstr); } + + // Import the extra size data + virtual size_t ExtraSize() const ATR_OVERRIDE { return Target::EXTRA_SIZE; } + virtual std::string defaultConfig() const ATR_OVERRIDE { return Target::defaultConfig; } + virtual bool verifyConfig(const SrtFilterConfig& config, std::string& w_errormsg) const ATR_OVERRIDE + { + return Target::verifyConfig(config, (w_errormsg)); + } + + public: + Creator() {} + virtual ~Creator() {} + }; + + + // We need a private wrapper for the auto-pointer, can't use + // std::unique_ptr here due to no C++11. + struct ManagedPtr + { + Factory* f; + mutable bool owns; + + // Accept whatever + ManagedPtr(Factory* ff): f(ff), owns(true) {} + ManagedPtr(): f(NULL), owns(false) {} + ~ManagedPtr() + { + if (owns) + delete f; + } + + void copy_internal(const ManagedPtr& other) + { + other.owns = false; + f = other.f; + owns = true; + } + + ManagedPtr(const ManagedPtr& other) + { + copy_internal(other); + } + + void operator=(const ManagedPtr& other) + { + if (owns) + delete f; + copy_internal(other); + } + + Factory* operator->() { return f; } + Factory* get() { return f; } + }; + + // The list of builtin names that are reserved. + static std::set builtin_filters; + + // Temporarily changed to linear searching, until this is exposed + // for a user-defined filter. + typedef std::map filters_map_t; + static filters_map_t filters; + + // This is a filter container. + SrtPacketFilterBase* m_filter; + void Check() + { +#if ENABLE_DEBUG + if (!m_filter) + abort(); +#endif + // Don't do any check for now. + } + +public: + + static void globalInit(); + + static bool IsBuiltin(const std::string&); + + template + static bool add(const std::string& name) + { + if (IsBuiltin(name)) + return false; + + filters[name] = new Creator; + return true; + } + + static Factory* find(const std::string& type) + { + filters_map_t::iterator i = filters.find(type); + if (i == filters.end()) + return NULL; // No matter what to return - this is "undefined behavior" to be prevented + return i->second.get(); + } + + // Filter is optional, so this check should be done always + // manually. + bool installed() const { return m_filter; } + operator bool() const { return installed(); } + + SrtPacketFilterBase* operator->() { Check(); return m_filter; } + + // In the beginning it's initialized as first, builtin default. + // Still, it will be created only when requested. + PacketFilter(): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // Copy constructor - important when listener-spawning + // Things being done: + // 1. The filter is individual, so don't copy it. Set NULL. + // 2. This will be configued anyway basing on possibly a new rule set. + PacketFilter(const PacketFilter& source SRT_ATR_UNUSED): m_filter(), m_parent(), m_sndctlpkt(0), m_unitq() {} + + // This function will be called by the parent CUDT + // in appropriate time. It should select appropriate + // filter basing on the value in selector, then + // pin oneself in into CUDT for receiving event signals. + bool configure(CUDT* parent, CUnitQueue* uq, const std::string& confstr); + + static bool correctConfig(const SrtFilterConfig& c); + + // Will delete the pinned in filter object. + // This must be defined in *.cpp file due to virtual + // destruction. + ~PacketFilter(); + + // Simple wrappers + void feedSource(CPacket& w_packet); + SRT_ARQLevel arqLevel(); + bool packControlPacket(int32_t seq, int kflg, CPacket& w_packet); + void receive(CUnit* unit, std::vector& w_incoming, loss_seqs_t& w_loss_seqs); + +protected: + PacketFilter& operator=(const PacketFilter& p); + void InsertRebuilt(std::vector& incoming, CUnitQueue* uq); + + CUDT* m_parent; + + // Sender part + SrtPacket m_sndctlpkt; + + // Receiver part + CUnitQueue* m_unitq; + std::vector m_provided; +}; + +bool CheckFilterCompat(SrtFilterConfig& w_agent, SrtFilterConfig peer); + +inline void PacketFilter::feedSource(CPacket& w_packet) { SRT_ASSERT(m_filter); return m_filter->feedSource((w_packet)); } +inline SRT_ARQLevel PacketFilter::arqLevel() { SRT_ASSERT(m_filter); return m_filter->arqLevel(); } + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& out, PacketFilter::Factory** ppf); + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_api.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_api.h new file mode 100644 index 000000000..3bfba7c76 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_api.h @@ -0,0 +1,158 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_PACKETFILTER_API_H +#define INC_SRT_PACKETFILTER_API_H + +#include "platform_sys.h" + +#include +#include +#include +#include +#include + +namespace srt { + +class CPacket; + +enum SrtPktHeaderFields +{ + SRT_PH_SEQNO = 0, //< sequence number + SRT_PH_MSGNO = 1, //< message number + SRT_PH_TIMESTAMP = 2, //< time stamp + SRT_PH_ID = 3, //< socket ID + + // Must be the last value - this is size of all, not a field id + SRT_PH_E_SIZE +}; + + +enum SRT_ARQLevel +{ + SRT_ARQ_NEVER, //< Never send LOSSREPORT + SRT_ARQ_ONREQ, //< Only record the loss, but report only those that are returned in receive() + SRT_ARQ_ALWAYS, //< always send LOSSREPORT immediately after detecting a loss +}; + +struct SrtConfig +{ + std::string type; + typedef std::map par_t; + par_t parameters; +}; + +struct SrtFilterConfig: SrtConfig +{ + size_t extra_size; // needed for filter option check against payload size +}; + +struct SrtFilterInitializer +{ + SRTSOCKET socket_id; + int32_t snd_isn; + int32_t rcv_isn; + size_t payload_size; + size_t rcvbuf_size; +}; + +struct SrtPacket +{ + uint32_t hdr[SRT_PH_E_SIZE]; + char buffer[SRT_LIVE_MAX_PLSIZE]; + size_t length; + + SrtPacket(size_t size): length(size) + { + memset(hdr, 0, sizeof(hdr)); + } + + uint32_t header(SrtPktHeaderFields field) { return hdr[field]; } + char* data() { return buffer; } + const char* data() const { return buffer; } + size_t size() const { return length; } +}; + + +bool ParseFilterConfig(const std::string& s, SrtFilterConfig& w_config); + + +class SrtPacketFilterBase +{ + SrtFilterInitializer initParams; + +protected: + + SRTSOCKET socketID() const { return initParams.socket_id; } + int32_t sndISN() const { return initParams.snd_isn; } + int32_t rcvISN() const { return initParams.rcv_isn; } + size_t payloadSize() const { return initParams.payload_size; } + size_t rcvBufferSize() const { return initParams.rcvbuf_size; } + + friend class PacketFilter; + + // Beside the size of the rows, special values: + // 0: if you have 0 specified for rows, there are only columns + // -1: Only during the handshake, use the value specified by peer. + // -N: The N value still specifies the size, but in particular + // dimension there is no filter control packet formed nor expected. + +public: + + typedef std::vector< std::pair > loss_seqs_t; + +protected: + + SrtPacketFilterBase(const SrtFilterInitializer& i): initParams(i) + { + } + + // Sender side + + /// This function creates and stores the filter control packet with + /// a prediction to be immediately sent. This is called in the function + /// that normally is prepared for extracting a data packet from the sender + /// buffer and send it over the channel. The returned value informs the + /// caller whether the control packet was available and therefore provided. + /// @param [OUT] packet Target place where the packet should be stored + /// @param [IN] seq Sequence number of the packet last requested for sending + /// @return true if the control packet has been provided + virtual bool packControlPacket(SrtPacket& packet, int32_t seq) = 0; + + /// This is called at the moment when the sender queue decided to pick up + /// a new packet from the scheduled packets. This should be then used to + /// continue filling the group, possibly followed by final calculating the + /// control packet ready to send. The packet received by this function is + /// potentially allowed to be modified. + /// @param [INOUT] packet The packet about to send + virtual void feedSource(CPacket& packet) = 0; + + + // Receiver side + + // This function is called at the moment when a new data packet has + // arrived (no matter if subsequent or recovered). The 'state' value + // defines the configured level of loss state required to send the + // loss report. + virtual bool receive(const CPacket& pkt, loss_seqs_t& loss_seqs) = 0; + + // Backward configuration. + // This should have some stable value after the configuration is parsed, + // and it should be a stable value set ONCE, after the filter module is ready. + virtual SRT_ARQLevel arqLevel() = 0; + + virtual ~SrtPacketFilterBase() + { + } +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_builtin.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_builtin.h new file mode 100644 index 000000000..80983250a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/packetfilter_builtin.h @@ -0,0 +1,18 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +#ifndef INC_SRT_PACKETFILTER_BUILTIN_H +#define INC_SRT_PACKETFILTER_BUILTIN_H + +// Integration header +#include "fec.h" + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/platform_sys.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/platform_sys.h index fae95803f..e2f0aa4d9 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/platform_sys.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/platform_sys.h @@ -7,28 +7,113 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ -#ifndef INC__PLATFORM_SYS_H -#define INC__PLATFORM_SYS_H +#ifndef INC_SRT_PLATFORM_SYS_H +#define INC_SRT_PLATFORM_SYS_H + +// INFORMATION +// +// This file collects all required platform-specific declarations +// required to provide everything that the SRT library needs from system. +// +// There's also semi-modular system implemented using SRT_IMPORT_* macros. +// To require a module to be imported, #define SRT_IMPORT_* where * is +// the module name. Currently handled module macros: +// +// SRT_IMPORT_TIME (mach time on Mac, portability gettimeofday on WIN32) +// SRT_IMPORT_EVENT (includes kevent on Mac) + #ifdef _WIN32 #include #include #include #include + +#ifndef __MINGW32__ + #include +#endif + + #ifdef SRT_IMPORT_TIME + #include + #endif + #include #include - #if defined(_MSC_VER) - #pragma warning(disable:4251) - #endif #else + +#if defined(__APPLE__) && __APPLE__ +// Warning: please keep this test as it is, do not make it +// "#if __APPLE__" or "#ifdef __APPLE__". In applications with +// a strict "no warning policy", "#if __APPLE__" triggers an "undef" +// error. With GCC, an old & never fixed bug prevents muting this +// warning (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431). +// Before this fix, the solution was to "#define __APPLE__ 0" before +// including srt.h. So, don't use "#ifdef __APPLE__" either. + +// XXX Check if this condition doesn't require checking of +// also other macros, like TARGET_OS_IOS etc. + +#include "TargetConditionals.h" +#define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ + +#ifdef SRT_IMPORT_TIME + #include +#endif + +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif + +#endif + +#ifdef BSD +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif +#endif + +#ifdef LINUX + +#ifdef SRT_IMPORT_EVENT + #include + #include +#endif + +#endif + +#ifdef __ANDROID__ + +#ifdef SRT_IMPORT_EVENT + #include +#endif + +#endif + #include #include +#include #include #include #include #include #include -#include +#include + +#ifdef __cplusplus +// Headers for errno, string and stdlib are +// included indirectly correct C++ way. +#else +#include +#include +#include +#endif + #endif #endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/queue.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/queue.h new file mode 100644 index 000000000..dd68a7721 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/queue.h @@ -0,0 +1,603 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/12/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_QUEUE_H +#define INC_SRT_QUEUE_H + +#include "common.h" +#include "packet.h" +#include "socketconfig.h" +#include "netinet_any.h" +#include "utilities.h" +#include +#include +#include +#include + +namespace srt +{ +class CChannel; +class CUDT; + +struct CUnit +{ + CPacket m_Packet; // packet + sync::atomic m_bTaken; // true if the unit is is use (can be stored in the RCV buffer). +}; + +class CUnitQueue +{ +public: + /// @brief Construct a unit queue. + /// @param mss Initial number of units to allocate. + /// @param mss Maximum segment size meaning the size of each unit. + /// @throws CUDTException SRT_ENOBUF. + CUnitQueue(int initNumUnits, int mss); + ~CUnitQueue(); + +public: + int capacity() const { return m_iSize; } + int size() const { return m_iSize - m_iNumTaken; } + +public: + /// @brief Find an available unit for incoming packet. Allocate new units if 90% or more are in use. + /// @note This function is not thread-safe. Currently only CRcvQueue::worker thread calls it, thus + /// it is not an issue. However, must be protected if used from several threads in the future. + /// @return Pointer to the available unit, NULL if not found. + CUnit* getNextAvailUnit(); + + void makeUnitFree(CUnit* unit); + + void makeUnitTaken(CUnit* unit); + +private: + struct CQEntry + { + CUnit* m_pUnit; // unit queue + char* m_pBuffer; // data buffer + int m_iSize; // size of each queue + + CQEntry* m_pNext; + }; + + /// Increase the unit queue size (by @a m_iBlockSize units). + /// Uses m_mtx to protect access and changes of the queue state. + /// @return 0: success, -1: failure. + int increase_(); + + /// @brief Allocated a CQEntry of iNumUnits with each unit of mss bytes. + /// @param iNumUnits a number of units to allocate + /// @param mss the size of each unit in bytes. + /// @return a pointer to a newly allocated entry on success, NULL otherwise. + static CQEntry* allocateEntry(const int iNumUnits, const int mss); + +private: + CQEntry* m_pQEntry; // pointer to the first unit queue + CQEntry* m_pCurrQueue; // pointer to the current available queue + CQEntry* m_pLastQueue; // pointer to the last unit queue + CUnit* m_pAvailUnit; // recent available unit + int m_iSize; // total size of the unit queue, in number of packets + sync::atomic m_iNumTaken; // total number of valid (occupied) packets in the queue + const int m_iMSS; // unit buffer size + const int m_iBlockSize; // Number of units in each CQEntry. + +private: + CUnitQueue(const CUnitQueue&); + CUnitQueue& operator=(const CUnitQueue&); +}; + +struct CSNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; + + sync::atomic m_iHeapLoc; // location on the heap, -1 means not on the heap +}; + +class CSndUList +{ +public: + CSndUList(sync::CTimer* pTimer); + ~CSndUList(); + +public: + enum EReschedule + { + DONT_RESCHEDULE = 0, + DO_RESCHEDULE = 1 + }; + + static EReschedule rescheduleIf(bool cond) { return cond ? DO_RESCHEDULE : DONT_RESCHEDULE; } + + /// Update the timestamp of the UDT instance on the list. + /// @param [in] u pointer to the UDT instance + /// @param [in] reschedule if the timestamp should be rescheduled + /// @param [in] ts the next time to trigger sending logic on the CUDT + void update(const CUDT* u, EReschedule reschedule, sync::steady_clock::time_point ts = sync::steady_clock::now()); + + /// Retrieve the next (in time) socket from the heap to process its sending request. + /// @return a pointer to CUDT instance to process next. + CUDT* pop(); + + /// Remove UDT instance from the list. + /// @param [in] u pointer to the UDT instance + void remove(const CUDT* u);// EXCLUDES(m_ListLock); + + /// Retrieve the next scheduled processing time. + /// @return Scheduled processing time of the first UDT socket in the list. + sync::steady_clock::time_point getNextProcTime(); + + /// Wait for the list to become non empty. + void waitNonEmpty() const; + + /// Signal to stop waiting in waitNonEmpty(). + void signalInterrupt() const; + +private: + /// Doubles the size of the list. + /// + void realloc_();// REQUIRES(m_ListLock); + + /// Insert a new UDT instance into the list with realloc if required. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_(const sync::steady_clock::time_point& ts, const CUDT* u); + + /// Insert a new UDT instance into the list without realloc. + /// Should be called if there is a guaranteed space for the element. + /// + /// @param [in] ts time stamp: next processing time + /// @param [in] u pointer to the UDT instance + void insert_norealloc_(const sync::steady_clock::time_point& ts, const CUDT* u);// REQUIRES(m_ListLock); + + /// Removes CUDT entry from the list. + /// If the last entry is removed, calls sync::CTimer::interrupt(). + void remove_(const CUDT* u); + +private: + CSNode** m_pHeap; // The heap array + int m_iArrayLength; // physical length of the array + int m_iLastEntry; // position of last entry on the heap array or -1 if empty. + + mutable sync::Mutex m_ListLock; // Protects the list (m_pHeap, m_iArrayLength, m_iLastEntry). + mutable sync::Condition m_ListCond; + + sync::CTimer* const m_pTimer; + +private: + CSndUList(const CSndUList&); + CSndUList& operator=(const CSndUList&); +}; + +struct CRNode +{ + CUDT* m_pUDT; // Pointer to the instance of CUDT socket + sync::steady_clock::time_point m_tsTimeStamp; // Time Stamp + + CRNode* m_pPrev; // previous link + CRNode* m_pNext; // next link + + sync::atomic m_bOnList; // if the node is already on the list +}; + +class CRcvUList +{ +public: + CRcvUList(); + ~CRcvUList(); + +public: + /// Insert a new UDT instance to the list. + /// @param [in] u pointer to the UDT instance + + void insert(const CUDT* u); + + /// Remove the UDT instance from the list. + /// @param [in] u pointer to the UDT instance + + void remove(const CUDT* u); + + /// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing. + /// @param [in] u pointer to the UDT instance + + void update(const CUDT* u); + +public: + CRNode* m_pUList; // the head node + +private: + CRNode* m_pLast; // the last node + +private: + CRcvUList(const CRcvUList&); + CRcvUList& operator=(const CRcvUList&); +}; + +class CHash +{ +public: + CHash(); + ~CHash(); + +public: + /// Initialize the hash table. + /// @param [in] size hash table size + + void init(int size); + + /// Look for a UDT instance from the hash table. + /// @param [in] id socket ID + /// @return Pointer to a UDT instance, or NULL if not found. + + CUDT* lookup(int32_t id); + + /// Insert an entry to the hash table. + /// @param [in] id socket ID + /// @param [in] u pointer to the UDT instance + + void insert(int32_t id, CUDT* u); + + /// Remove an entry from the hash table. + /// @param [in] id socket ID + + void remove(int32_t id); + +private: + struct CBucket + { + int32_t m_iID; // Socket ID + CUDT* m_pUDT; // Socket instance + + CBucket* m_pNext; // next bucket + } * *m_pBucket; // list of buckets (the hash table) + + int m_iHashSize; // size of hash table + +private: + CHash(const CHash&); + CHash& operator=(const CHash&); +}; + +/// @brief A queue of sockets pending for connection. +/// It can be either a caller socket in a non-blocking mode +/// (the connection has to be handled in background), +/// or a socket in rendezvous connection mode. +class CRendezvousQueue +{ +public: + CRendezvousQueue(); + ~CRendezvousQueue(); + +public: + /// @brief Insert a new socket pending for connection (non-blocking caller or rendezvous). + /// @param id socket ID. + /// @param u pointer to a corresponding CUDT instance. + /// @param addr remote address to connect to. + /// @param ttl timepoint for connection attempt to expire. + void insert(const SRTSOCKET& id, CUDT* u, const sockaddr_any& addr, const srt::sync::steady_clock::time_point& ttl); + + /// @brief Remove a socket from the connection pending list. + /// @param id socket ID. + void remove(const SRTSOCKET& id); + + /// @brief Locate a socket in the connection pending queue. + /// @param addr source address of the packet received over UDP (peer address). + /// @param id socket ID. + /// @return a pointer to CUDT instance retrieved, or NULL if nothing was found. + CUDT* retrieve(const sockaddr_any& addr, SRTSOCKET& id) const; + + /// @brief Update status of connections in the pending queue. + /// Stop connecting if TTL expires. Resend handshake request every 250 ms if no response from the peer. + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param pktIn packet received from the UDP socket. + void updateConnStatus(EReadStatus rst, EConnectStatus cst, CUnit* unit); + +private: + struct LinkStatusInfo + { + CUDT* u; + SRTSOCKET id; + int errorcode; + sockaddr_any peeraddr; + int token; + + struct HasID + { + SRTSOCKET id; + HasID(SRTSOCKET p) + : id(p) + { + } + bool operator()(const LinkStatusInfo& i) { return i.id == id; } + }; + }; + + /// @brief Qualify pending connections: + /// - Sockets with expired TTL go to the 'to_remove' list and removed from the queue straight away. + /// - If HS request is to be resent (resend 250 ms if no response from the peer) go to the 'to_process' list. + /// + /// @param rst result of reading from a UDP socket: received packet / nothin read / read error. + /// @param cst target status for pending connection: reject or proceed. + /// @param iDstSockID destination socket ID of the received packet. + /// @param[in,out] toRemove stores sockets with expired TTL. + /// @param[in,out] toProcess stores sockets which should repeat (resend) HS connection request. + bool qualifyToHandle(EReadStatus rst, + EConnectStatus cst, + int iDstSockID, + std::vector& toRemove, + std::vector& toProcess); + +private: + struct CRL + { + SRTSOCKET m_iID; // SRT socket ID (self) + CUDT* m_pUDT; // CUDT instance + sockaddr_any m_PeerAddr; // SRT sonnection peer address + sync::steady_clock::time_point m_tsTTL; // the time that this request expires + }; + std::list m_lRendezvousID; // The sockets currently in rendezvous mode + + mutable sync::Mutex m_RIDListLock; +}; + +class CSndQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CSndQueue(); + ~CSndQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working for. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the sending queue. + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t Timer + void init(CChannel* c, sync::CTimer* t); + + /// Send out a packet to a given address. The @a src parameter is + /// blindly passed by the caller down the call with intention to + /// be received eventually by CChannel::sendto, and used only if + /// appropriate conditions state so. + /// @param [in] addr destination address + /// @param [in,ref] packet packet to be sent out + /// @param [in] src The source IP address (details above) + /// @return Size of data sent out. + int sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& src); + + /// Get the IP TTL. + /// @param [in] ttl IP Time To Live. + /// @return TTL. + int getIpTTL() const; + + /// Get the IP Type of Service. + /// @return ToS. + int getIpToS() const; + +#ifdef SRT_ENABLE_BINDTODEVICE + bool getBind(char* dst, size_t len) const; +#endif + + int ioctlQuery(int type) const; + int sockoptQuery(int level, int type) const; + + void setClosing() { m_bClosing = true; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + +private: + CSndUList* m_pSndUList; // List of UDT instances for data sending + CChannel* m_pChannel; // The UDP channel for data sending + sync::CTimer* m_pTimer; // Timing facility + + sync::atomic m_bClosing; // closing the worker + +public: +#if defined(SRT_DEBUG_SNDQ_HIGHRATE) //>>debug high freq worker + sync::steady_clock::duration m_DbgPeriod; + mutable sync::steady_clock::time_point m_DbgTime; + struct + { + unsigned long lIteration; // + unsigned long lSleepTo; // SleepTo + unsigned long lNotReadyPop; // Continue + unsigned long lSendTo; + unsigned long lNotReadyTs; + unsigned long lCondWait; // block on m_WindowCond + } mutable m_WorkerStats; +#endif /* SRT_DEBUG_SNDQ_HIGHRATE */ + +private: + +#if ENABLE_LOGGING + static int m_counter; +#endif + + CSndQueue(const CSndQueue&); + CSndQueue& operator=(const CSndQueue&); +}; + +class CRcvQueue +{ + friend class CUDT; + friend class CUDTUnited; + +public: + CRcvQueue(); + ~CRcvQueue(); + +public: + // XXX There's currently no way to access the socket ID set for + // whatever the queue is currently working. Required to find + // some way to do this, possibly by having a "reverse pointer". + // Currently just "unimplemented". + std::string CONID() const { return ""; } + + /// Initialize the receiving queue. + /// @param [in] size queue size + /// @param [in] mss maximum packet size + /// @param [in] version IP version + /// @param [in] hsize hash table size + /// @param [in] c UDP channel to be associated to the queue + /// @param [in] t timer + void init(int size, size_t payload, int version, int hsize, CChannel* c, sync::CTimer* t); + + /// Read a packet for a specific UDT socket id. + /// @param [in] id Socket ID + /// @param [out] packet received packet + /// @return Data size of the packet + int recvfrom(int32_t id, CPacket& to_packet); + + void stopWorker(); + + void setClosing() { m_bClosing = true; } + + int getIPversion() { return m_iIPversion; } + +private: + static void* worker(void* param); + sync::CThread m_WorkerThread; + // Subroutines of worker + EReadStatus worker_RetrieveUnit(int32_t& id, CUnit*& unit, sockaddr_any& sa); + EConnectStatus worker_ProcessConnectionRequest(CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_TryAsyncRend_OrStore(int32_t id, CUnit* unit, const sockaddr_any& sa); + EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr_any& sa); + +private: + CUnitQueue* m_pUnitQueue; // The received packet queue + CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue + CHash* m_pHash; // Hash table for UDT socket looking up + CChannel* m_pChannel; // UDP channel for receiving packets + sync::CTimer* m_pTimer; // shared timer with the snd queue + + int m_iIPversion; // IP version + size_t m_szPayloadSize; // packet payload size + + sync::atomic m_bClosing; // closing the worker +#if ENABLE_LOGGING + static srt::sync::atomic m_counter; // A static counter to log RcvQueue worker thread number. +#endif + +private: + int setListener(CUDT* u); + void removeListener(const CUDT* u); + + void registerConnector(const SRTSOCKET& id, + CUDT* u, + const sockaddr_any& addr, + const sync::steady_clock::time_point& ttl); + void removeConnector(const SRTSOCKET& id); + + void setNewEntry(CUDT* u); + bool ifNewEntry(); + CUDT* getNewEntry(); + + void storePktClone(int32_t id, const CPacket& pkt); + +private: + sync::Mutex m_LSLock; + CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity + CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode + + std::vector m_vNewEntry; // newly added entries, to be inserted + sync::Mutex m_IDLock; + + std::map > m_mBuffer; // temporary buffer for rendezvous connection request + sync::Mutex m_BufferLock; + sync::Condition m_BufferCond; + +private: + CRcvQueue(const CRcvQueue&); + CRcvQueue& operator=(const CRcvQueue&); +}; + +struct CMultiplexer +{ + CSndQueue* m_pSndQueue; // The sending queue + CRcvQueue* m_pRcvQueue; // The receiving queue + CChannel* m_pChannel; // The UDP channel for sending and receiving + sync::CTimer* m_pTimer; // The timer + + int m_iPort; // The UDP port number of this multiplexer + int m_iIPversion; // Address family (AF_INET or AF_INET6) + int m_iRefCount; // number of UDT instances that are associated with this multiplexer + + CSrtMuxerConfig m_mcfg; + + int m_iID; // multiplexer ID + + // Constructor should reset all pointers to NULL + // to prevent dangling pointer when checking for memory alloc fails + CMultiplexer() + : m_pSndQueue(NULL) + , m_pRcvQueue(NULL) + , m_pChannel(NULL) + , m_pTimer(NULL) + { + } + + void destroy(); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/socketconfig.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/socketconfig.h new file mode 100644 index 000000000..403616edf --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/socketconfig.h @@ -0,0 +1,410 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_SOCKETCONFIG_H +#define INC_SRT_SOCKETCONFIG_H + +#include "platform_sys.h" +#ifdef SRT_ENABLE_BINDTODEVICE +#include +#endif +#include +#include "haicrypt.h" +#include "congctl.h" +#include "packet.h" +#include "handshake.h" +#include "logger_defs.h" +#include "packetfilter.h" + +// SRT Version constants +#define SRT_VERSION_UNK 0 +#define SRT_VERSION_MAJ1 0x010000 /* Version 1 major */ +#define SRT_VERSION_MAJ(v) (0xFF0000 & (v)) /* Major number ensuring backward compatibility */ +#define SRT_VERSION_MIN(v) (0x00FF00 & (v)) +#define SRT_VERSION_PCH(v) (0x0000FF & (v)) + +// NOTE: SRT_VERSION is primarily defined in the build file. +extern const int32_t SRT_DEF_VERSION; + +namespace srt +{ + +struct CSrtMuxerConfig +{ + static const int DEF_UDP_BUFFER_SIZE = 65536; + + int iIpTTL; + int iIpToS; + int iIpV6Only; // IPV6_V6ONLY option (-1 if not set) + bool bReuseAddr; // reuse an exiting port or not, for UDP multiplexer + +#ifdef SRT_ENABLE_BINDTODEVICE + std::string sBindToDevice; +#endif + int iUDPSndBufSize; // UDP sending buffer size + int iUDPRcvBufSize; // UDP receiving buffer size + + // NOTE: this operator is not reversable. The syntax must use: + // muxer_entry == socket_entry + bool isCompatWith(const CSrtMuxerConfig& other) const + { +#define CEQUAL(field) (field == other.field) + return CEQUAL(iIpTTL) + && CEQUAL(iIpToS) + && CEQUAL(bReuseAddr) +#ifdef SRT_ENABLE_BINDTODEVICE + && CEQUAL(sBindToDevice) +#endif + && CEQUAL(iUDPSndBufSize) + && CEQUAL(iUDPRcvBufSize) + && (other.iIpV6Only == -1 || CEQUAL(iIpV6Only)) + // NOTE: iIpV6Only is not regarded because + // this matches only in case of IPv6 with "any" address. + // And this aspect must be checked separately because here + // this procedure has no access to neither the address, + // nor the IP version (family). +#undef CEQUAL + && true; + } + + CSrtMuxerConfig() + : iIpTTL(-1) /* IPv4 TTL or IPv6 HOPs [1..255] (-1:undefined) */ + , iIpToS(-1) /* IPv4 Type of Service or IPv6 Traffic Class [0x00..0xff] (-1:undefined) */ + , iIpV6Only(-1) + , bReuseAddr(true) // This is default in SRT + , iUDPSndBufSize(DEF_UDP_BUFFER_SIZE) + , iUDPRcvBufSize(DEF_UDP_BUFFER_SIZE) + { + } +}; + +struct CSrtConfig; + +template +class StringStorage +{ + char stor[SIZE + 1]; + uint16_t len; + + // NOTE: default copying allowed. + +public: + StringStorage() + : len(0) + { + memset(stor, 0, sizeof stor); + } + + bool set(const char* s, size_t length) + { + if (length > SIZE) + return false; + + memcpy(stor, s, length); + stor[length] = 0; + len = (int) length; + return true; + } + + bool set(const std::string& s) + { + return set(s.c_str(), s.size()); + } + + size_t copy(char* s, size_t length) const + { + if (!s) + return 0; + + size_t copy_len = std::min((size_t)len, length); + memcpy(s, stor, copy_len); + return copy_len; + } + + std::string str() const + { + return len == 0 ? std::string() : std::string(stor); + } + + const char* c_str() const + { + return stor; + } + + size_t size() const { return size_t(len); } + bool empty() const { return len == 0; } +}; + +struct CSrtConfig: CSrtMuxerConfig +{ + typedef srt::sync::steady_clock::time_point time_point; + typedef srt::sync::steady_clock::duration duration; + + static const int + DEF_MSS = 1500, + DEF_FLIGHT_SIZE = 25600, + DEF_BUFFER_SIZE = 8192, //Rcv buffer MUST NOT be bigger than Flight Flag size + DEF_LINGER_S = 3*60, // 3 minutes + DEF_CONNTIMEO_S = 3; // 3 seconds + + enum + { + CIPHER_MODE_AUTO = 0, + CIPHER_MODE_AES_CTR = 1, + CIPHER_MODE_AES_GCM = 2 + }; + + static const int COMM_RESPONSE_TIMEOUT_MS = 5 * 1000; // 5 seconds + static const uint32_t COMM_DEF_MIN_STABILITY_TIMEOUT_MS = 60; // 60 ms + + // Mimimum recv flight flag size is 32 packets + static const int DEF_MIN_FLIGHT_PKT = 32; + static const size_t MAX_SID_LENGTH = 512; + static const size_t MAX_PFILTER_LENGTH = 64; + static const size_t MAX_CONG_LENGTH = 16; + + int iMSS; // Maximum Segment Size, in bytes + size_t zExpPayloadSize; // Expected average payload size (user option) + + // Options + bool bSynSending; // Sending synchronization mode + bool bSynRecving; // Receiving synchronization mode + int iFlightFlagSize; // Maximum number of packets in flight from the peer side + int iSndBufSize; // Maximum UDT sender buffer size + int iRcvBufSize; // Maximum UDT receiver buffer size + linger Linger; // Linger information on close + bool bRendezvous; // Rendezvous connection mode + + duration tdConnTimeOut; // connect timeout in milliseconds + bool bDriftTracer; + int iSndTimeOut; // sending timeout in milliseconds + int iRcvTimeOut; // receiving timeout in milliseconds + int64_t llMaxBW; // maximum data transfer rate (threshold) +#ifdef ENABLE_MAXREXMITBW + int64_t llMaxRexmitBW; // maximum bandwidth limit for retransmissions (Bytes/s). +#endif + + // These fields keep the options for encryption + // (SRTO_PASSPHRASE, SRTO_PBKEYLEN). Crypto object is + // created later and takes values from these. + HaiCrypt_Secret CryptoSecret; + int iSndCryptoKeyLen; + + // XXX Consider removing. The bDataSender stays here + // in order to maintain the HS side selection in HSv4. + bool bDataSender; + + bool bMessageAPI; + bool bTSBPD; // Whether AGENT will do TSBPD Rx (whether peer does, is not agent's problem) + int iRcvLatency; // Agent's Rx latency + int iPeerLatency; // Peer's Rx latency for the traffic made by Agent's Tx. + bool bTLPktDrop; // Whether Agent WILL DO TLPKTDROP on Rx. + int iSndDropDelay; // Extra delay when deciding to snd-drop for TLPKTDROP, -1 to off + bool bEnforcedEnc; // Off by default. When on, any connection other than nopw-nopw & pw1-pw1 is rejected. + int iGroupConnect; // 1 - allow group connections + int iPeerIdleTimeout_ms; // Timeout for hearing anything from the peer (ms). + uint32_t uMinStabilityTimeout_ms; + int iRetransmitAlgo; + int iCryptoMode; // SRTO_CRYPTOMODE + + int64_t llInputBW; // Input stream rate (bytes/sec). 0: use internally estimated input bandwidth + int64_t llMinInputBW; // Minimum input stream rate estimate (bytes/sec) + int iOverheadBW; // Percent above input stream rate (applies if llMaxBW == 0) + bool bRcvNakReport; // Enable Receiver Periodic NAK Reports + int iMaxReorderTolerance; //< Maximum allowed value for dynamic reorder tolerance + + // For the use of CCryptoControl + // HaiCrypt configuration + unsigned int uKmRefreshRatePkt; + unsigned int uKmPreAnnouncePkt; + + uint32_t uSrtVersion; + uint32_t uMinimumPeerSrtVersion; + + StringStorage sCongestion; + StringStorage sPacketFilterConfig; + StringStorage sStreamName; + + // Shortcuts and utilities + int32_t flightCapacity() + { + return std::min(iRcvBufSize, iFlightFlagSize); + } + + CSrtConfig() + : iMSS(DEF_MSS) + , zExpPayloadSize(SRT_LIVE_DEF_PLSIZE) + , bSynSending(true) + , bSynRecving(true) + , iFlightFlagSize(DEF_FLIGHT_SIZE) + , iSndBufSize(DEF_BUFFER_SIZE) + , iRcvBufSize(DEF_BUFFER_SIZE) + , bRendezvous(false) + , tdConnTimeOut(srt::sync::seconds_from(DEF_CONNTIMEO_S)) + , bDriftTracer(true) + , iSndTimeOut(-1) + , iRcvTimeOut(-1) + , llMaxBW(-1) +#ifdef ENABLE_MAXREXMITBW + , llMaxRexmitBW(-1) +#endif + , bDataSender(false) + , bMessageAPI(true) + , bTSBPD(true) + , iRcvLatency(SRT_LIVE_DEF_LATENCY_MS) + , iPeerLatency(0) + , bTLPktDrop(true) + , iSndDropDelay(0) + , bEnforcedEnc(true) + , iGroupConnect(0) + , iPeerIdleTimeout_ms(COMM_RESPONSE_TIMEOUT_MS) + , uMinStabilityTimeout_ms(COMM_DEF_MIN_STABILITY_TIMEOUT_MS) + , iRetransmitAlgo(1) + , iCryptoMode(CIPHER_MODE_AUTO) + , llInputBW(0) + , llMinInputBW(0) + , iOverheadBW(25) + , bRcvNakReport(true) + , iMaxReorderTolerance(0) // Sensible optimal value is 10, 0 preserves old behavior + , uKmRefreshRatePkt(0) + , uKmPreAnnouncePkt(0) + , uSrtVersion(SRT_DEF_VERSION) + , uMinimumPeerSrtVersion(SRT_VERSION_MAJ1) + + { + // Default UDT configurations + iUDPRcvBufSize = iRcvBufSize * iMSS; + + // Linger: LIVE mode defaults, please refer to `SRTO_TRANSTYPE` option + // for other modes. + Linger.l_onoff = 0; + Linger.l_linger = 0; + CryptoSecret.len = 0; + iSndCryptoKeyLen = 0; + + // Default congestion is "live". + // Available builtin congestions: "file". + // Others can be registerred. + sCongestion.set("live", 4); + } + + ~CSrtConfig() + { + // Wipeout critical data + memset(&CryptoSecret, 0, sizeof(CryptoSecret)); + } + + int set(SRT_SOCKOPT optName, const void* val, int size); +}; + +template +inline T cast_optval(const void* optval) +{ + return *reinterpret_cast(optval); +} + +template +inline T cast_optval(const void* optval, int optlen) +{ + if (optlen > 0 && optlen != sizeof(T)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + + return cast_optval(optval); +} + +// This function is to make it possible for both C and C++ +// API to accept both bool and int types for boolean options. +// (it's not that C couldn't use , it's that people +// often forget to use correct type). +template <> +inline bool cast_optval(const void* optval, int optlen) +{ + if (optlen == sizeof(bool)) + { + return *reinterpret_cast(optval); + } + + if (optlen == sizeof(int)) + { + // 0!= is a windows warning-killer int-to-bool conversion + return 0 != *reinterpret_cast(optval); + } + return false; +} + +} // namespace srt + +struct SRT_SocketOptionObject +{ + struct SingleOption + { + uint16_t option; + uint16_t length; + unsigned char storage[1]; // NOTE: Variable length object! + }; + + std::vector options; + + SRT_SocketOptionObject() {} + + ~SRT_SocketOptionObject() + { + for (size_t i = 0; i < options.size(); ++i) + { + // Convert back + unsigned char* mem = reinterpret_cast(options[i]); + delete[] mem; + } + } + + bool add(SRT_SOCKOPT optname, const void* optval, size_t optlen); +}; + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt.h index 0e566e859..53b6fd274 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt.h @@ -13,8 +13,8 @@ written by Haivision Systems Inc. *****************************************************************************/ -#ifndef INC__SRTC_H -#define INC__SRTC_H +#ifndef INC_SRTC_H +#define INC_SRTC_H #include "version.h" @@ -23,7 +23,6 @@ written by #include #include -#include "srt4udt.h" #include "logging_api.h" //////////////////////////////////////////////////////////////////////////////// @@ -36,7 +35,7 @@ written by #ifdef _WIN32 - #ifndef __MINGW__ + #ifndef __MINGW32__ // Explicitly define 32-bit and 64-bit numbers typedef __int32 int32_t; typedef __int64 int64_t; @@ -47,17 +46,14 @@ written by // VC 6.0 does not support unsigned __int64: may cause potential problems. typedef __int64 uint64_t; #endif - - #ifdef SRT_DYNAMIC - #ifdef SRT_EXPORTS - #define SRT_API __declspec(dllexport) - #else - #define SRT_API __declspec(dllimport) - #endif + #endif + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) #else - #define SRT_API + #define SRT_API __declspec(dllimport) #endif - #else // __MINGW__ + #else // !SRT_DYNAMIC #define SRT_API #endif #else @@ -69,48 +65,99 @@ written by // You can use these constants with SRTO_MINVERSION option. #define SRT_VERSION_FEAT_HSv5 0x010300 +#if defined(__cplusplus) && __cplusplus > 201406 +#define SRT_HAVE_CXX17 1 +#else +#define SRT_HAVE_CXX17 0 +#endif + + +// Standard attributes + // When compiling in C++17 mode, use the standard C++17 attributes // (out of these, only [[deprecated]] is supported in C++14, so // for all lesser standard use compiler-specific attributes). -#if defined(SRT_NO_DEPRECATED) - -#define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED -#define SRT_ATR_NODISCARD - -#elif defined(__cplusplus) && __cplusplus > 201406 +#if SRT_HAVE_CXX17 +// Unused: DO NOT issue a warning if this entity is unused. #define SRT_ATR_UNUSED [[maybe_unused]] -#define SRT_ATR_DEPRECATED [[deprecated]] + +// Nodiscard: issue a warning if the return value was discarded. #define SRT_ATR_NODISCARD [[nodiscard]] // GNUG is GNU C/C++; this syntax is also supported by Clang -#elif defined( __GNUC__) +#elif defined(__GNUC__) #define SRT_ATR_UNUSED __attribute__((unused)) -#define SRT_ATR_DEPRECATED __attribute__((deprecated)) #define SRT_ATR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define SRT_ATR_UNUSED __pragma(warning(suppress: 4100 4101)) +#define SRT_ATR_NODISCARD _Check_return_ #else #define SRT_ATR_UNUSED -#define SRT_ATR_DEPRECATED #define SRT_ATR_NODISCARD #endif + +// DEPRECATED attributes + +// There's needed DEPRECATED and DEPRECATED_PX, as some compilers require them +// before the entity, others after the entity. +// The *_PX version is the prefix attribute, which applies only +// to functions (Microsoft compilers). + +// When deprecating a function, mark it: +// +// SRT_ATR_DEPRECATED_PX retval function(arguments) SRT_ATR_DEPRECATED; +// + +// When SRT_NO_DEPRECATED defined, do not issue any deprecation warnings. +// Regardless of the compiler type. +#if defined(SRT_NO_DEPRECATED) + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX + +#elif SRT_HAVE_CXX17 + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX [[deprecated]] + +// GNUG is GNU C/C++; this syntax is also supported by Clang +#elif defined(__GNUC__) +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SRT_ATR_DEPRECATED_PX __declspec(deprecated) +#define SRT_ATR_DEPRECATED // no postfix-type modifier +#else +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED +#endif + #ifdef __cplusplus extern "C" { #endif -typedef int SRTSOCKET; // SRTSOCKET is a typedef to int anyway, and it's not even in UDT namespace :) +typedef int32_t SRTSOCKET; + +// The most significant bit 31 (sign bit actually) is left unused, +// so that all people who check the value for < 0 instead of -1 +// still get what they want. The bit 30 is reserved for marking +// the "socket group". Most of the API functions should work +// transparently with the socket descriptor designating a single +// socket or a socket group. +static const int32_t SRTGROUP_MASK = (1 << 30); #ifdef _WIN32 - #ifndef __MINGW__ - typedef SOCKET SYSSOCKET; - #else - typedef int SYSSOCKET; - #endif + typedef SOCKET SYSSOCKET; #else typedef int SYSSOCKET; #endif +#ifndef ENABLE_BONDING +#define ENABLE_BONDING 0 +#endif + typedef SYSSOCKET UDPSOCKET; @@ -141,8 +188,7 @@ typedef enum SRT_SOCKOPT { SRTO_LINGER = 7, // waiting for unsent data when closing SRTO_UDP_SNDBUF = 8, // UDP sending buffer size SRTO_UDP_RCVBUF = 9, // UDP receiving buffer size - // XXX Free space for 2 options - // after deprecated ones are removed + // (some space left) SRTO_RENDEZVOUS = 12, // rendezvous connection mode SRTO_SNDTIMEO = 13, // send() timeout SRTO_RCVTIMEO = 14, // recv() timeout @@ -155,11 +201,10 @@ typedef enum SRT_SOCKOPT { SRTO_SENDER = 21, // Sender mode (independent of conn mode), for encryption, tsbpd handshake. SRTO_TSBPDMODE = 22, // Enable/Disable TsbPd. Enable -> Tx set origin timestamp, Rx deliver packet at origin time + delay SRTO_LATENCY = 23, // NOT RECOMMENDED. SET: to both SRTO_RCVLATENCY and SRTO_PEERLATENCY. GET: same as SRTO_RCVLATENCY. - SRTO_TSBPDDELAY = 23, // DEPRECATED. ALIAS: SRTO_LATENCY SRTO_INPUTBW = 24, // Estimated input stream rate. SRTO_OHEADBW, // MaxBW ceiling based on % over input stream rate. Applies when UDT_MAXBW=0 (auto). - SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto - SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (128-bit) + SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase (must be 10..79 characters, or empty to disable encryption) + SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (AES-128) SRTO_KMSTATE, // Key Material exchange status (UDT_SRTKmState) SRTO_IPTTL = 29, // IP Time To Live (passthru for system sockopt IPPROTO_IP/IP_TTL) SRTO_IPTOS, // IP Type of Service (passthru for system sockopt IPPROTO_IP/IP_TOS) @@ -168,10 +213,10 @@ typedef enum SRT_SOCKOPT { SRTO_NAKREPORT = 33, // Enable receiver to send periodic NAK reports SRTO_VERSION = 34, // Local SRT Version SRTO_PEERVERSION, // Peer SRT Version (from SRT Handshake) - SRTO_CONNTIMEO = 36, // Connect timeout in msec. Ccaller default: 3000, rendezvous (x 10) - // deprecated: SRTO_TWOWAYDATA, SRTO_SNDPBKEYLEN, SRTO_RCVPBKEYLEN (@c below) - _DEPRECATED_SRTO_SNDPBKEYLEN = 38, // (needed to use inside the code without generating -Wswitch) - // + SRTO_CONNTIMEO = 36, // Connect timeout in msec. Caller default: 3000, rendezvous (x 10) + SRTO_DRIFTTRACER = 37, // Enable or disable drift tracer + SRTO_MININPUTBW = 38, // Minimum estimate of input stream rate. + // (some space left) SRTO_SNDKMSTATE = 40, // (GET) the current state of the encryption at the peer side SRTO_RCVKMSTATE, // (GET) the current state of the encryption at the agent side SRTO_LOSSMAXTTL, // Maximum possible packet reorder tolerance (number of packets to receive after loss to send lossreport) @@ -188,15 +233,40 @@ typedef enum SRT_SOCKOPT { SRTO_ENFORCEDENCRYPTION, // Connection to be rejected or quickly broken when one side encryption set or bad password SRTO_IPV6ONLY, // IPV6_V6ONLY mode SRTO_PEERIDLETIMEO, // Peer-idle timeout (max time of silence heard from peer) in [ms] - // (some space left) - SRTO_PACKETFILTER = 60 // Add and configure a packet filter + SRTO_BINDTODEVICE, // Forward the SOL_SOCKET/SO_BINDTODEVICE option on socket (pass packets only from that device) + SRTO_GROUPCONNECT, // Set on a listener to allow group connection (ENABLE_BONDING) + SRTO_GROUPMINSTABLETIMEO, // Minimum Link Stability timeout (backup mode) in milliseconds (ENABLE_BONDING) + SRTO_GROUPTYPE, // Group type to which an accepted socket is about to be added, available in the handshake (ENABLE_BONDING) + SRTO_PACKETFILTER = 60, // Add and configure a packet filter + SRTO_RETRANSMITALGO = 61, // An option to select packet retransmission algorithm +#ifdef ENABLE_AEAD_API_PREVIEW + SRTO_CRYPTOMODE = 62, // Encryption cipher mode (AES-CTR, AES-GCM, ...). +#endif +#ifdef ENABLE_MAXREXMITBW + SRTO_MAXREXMITBW = 63, // Maximum bandwidth limit for retransmision (Bytes/s) +#endif + + SRTO_E_SIZE // Always last element, not a valid option. } SRT_SOCKOPT; #ifdef __cplusplus -typedef SRT_ATR_DEPRECATED SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED; + +#if __cplusplus > 199711L // C++11 + // Newer compilers report error when [[deprecated]] is applied to types, + // and C++11 and higher uses this. + // Note that this doesn't exactly use the 'deprecated' attribute, + // as it's introduced in C++14. What is actually used here is the + // fact that unknown attributes are ignored, but still warned about. + // This should only catch an eye - and that's what it does. +#define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT [[deprecated]])value) +#else + // Older (pre-C++11) compilers use gcc deprecated applied to a typedef + typedef SRT_ATR_DEPRECATED_PX SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED SRT_ATR_DEPRECATED; #define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT_DEPRECATED)value) +#endif + #else @@ -213,46 +283,9 @@ enum SRT_ATR_DEPRECATED SRT_SOCKOPT_DEPRECATED #define SRT_DEPRECATED_OPTION(value) ((enum SRT_SOCKOPT_DEPRECATED)value) #endif -// DEPRECATED OPTIONS: - -// SRTO_TWOWAYDATA: not to be used. SRT connection is always bidirectional if -// both clients support HSv5 - that is, since version 1.3.0. This flag was -// introducted around 1.2.0 version when full bidirectional support was added, -// but the bidirectional feature was decided no to be enabled due to huge -// differences between bidirectional support (especially concerning encryption) -// with HSv4 and HSv5 (that is, HSv4 was decided to remain unidirectional only, -// even though partial support is already provided in this version). - -#define SRTO_TWOWAYDATA SRT_DEPRECATED_OPTION(37) - -// This has been deprecated a long time ago, treat this as never implemented. -// The value is also already reused for another option. -#define SRTO_TSBPDMAXLAG SRT_DEPRECATED_OPTION(32) - -// This option is a derivative from UDT; the mechanism that uses it is now -// settable by SRTO_CONGESTION, or more generally by SRTO_TRANSTYPE. The freed -// number has been reused for a read-only option SRTO_ISN. This option should -// have never been used anywhere, just for safety this is temporarily declared -// as deprecated. -#define SRTO_CC SRT_DEPRECATED_OPTION(3) - -// These two flags were derived from UDT, but they were never used. -// Probably it didn't make sense anyway. The maximum size of the message -// in File/Message mode is defined by SRTO_SNDBUF, and the MSGTTL is -// a parameter used in `srt_sendmsg` and `srt_sendmsg2`. -#define SRTO_MAXMSG SRT_DEPRECATED_OPTION(10) -#define SRTO_MSGTTL SRT_DEPRECATED_OPTION(11) - -// These flags come from an older experimental implementation of bidirectional -// encryption support, which were used two different SEKs, KEKs and passphrases -// per direction. The current implementation uses just one in both directions, -// so SRTO_PBKEYLEN should be used for both cases. -#define SRTO_SNDPBKEYLEN SRT_DEPRECATED_OPTION(38) -#define SRTO_RCVPBKEYLEN SRT_DEPRECATED_OPTION(39) - -// Keeping old name for compatibility (deprecated) -#define SRTO_SMOOTHER SRT_DEPRECATED_OPTION(47) -#define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) +// Note that there are no deprecated options at the moment, but the mechanism +// stays so that it can be used in future. Example: +// #define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) typedef enum SRT_TRANSTYPE { @@ -295,9 +328,7 @@ struct CBytePerfMon int pktRcvUndecryptTotal; // number of undecrypted packets uint64_t byteSentTotal; // total number of sent data bytes, including retransmissions uint64_t byteRecvTotal; // total number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLossTotal; // total number of lost bytes -#endif uint64_t byteRetransTotal; // total number of retransmitted bytes uint64_t byteSndDropTotal; // number of too-late-to-send dropped bytes uint64_t byteRcvDropTotal; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -327,9 +358,7 @@ struct CBytePerfMon int pktRcvUndecrypt; // number of undecrypted packets uint64_t byteSent; // number of sent data bytes, including retransmissions uint64_t byteRecv; // number of received bytes -#ifdef SRT_ENABLE_LOSTBYTESCOUNT uint64_t byteRcvLoss; // number of retransmitted bytes -#endif uint64_t byteRetrans; // number of retransmitted bytes uint64_t byteSndDrop; // number of too-late-to-send dropped bytes uint64_t byteRcvDrop; // number of too-late-to play missing bytes (estimate based on average packet size) @@ -370,6 +399,20 @@ struct CBytePerfMon int pktRcvFilterLoss; // number of packet loss not coverable by filter int pktReorderTolerance; // packet reorder tolerance value //< + + // New stats in 1.5.0 + + // Total + int64_t pktSentUniqueTotal; // total number of data packets sent by the application + int64_t pktRecvUniqueTotal; // total number of packets to be received by the application + uint64_t byteSentUniqueTotal; // total number of data bytes, sent by the application + uint64_t byteRecvUniqueTotal; // total number of data bytes to be received by the application + + // Local + int64_t pktSentUnique; // number of data packets sent by the application + int64_t pktRecvUnique; // number of packets to be received by the application + uint64_t byteSentUnique; // number of data bytes, sent by the application + uint64_t byteRecvUnique; // number of data bytes to be received by the application }; //////////////////////////////////////////////////////////////////////////////// @@ -399,12 +442,14 @@ enum CodeMinor MN_REJECTED = 2, MN_NORES = 3, MN_SECURITY = 4, + MN_CLOSED = 5, // MJ_CONNECTION MN_CONNLOST = 1, MN_NOCONN = 2, // MJ_SYSTEMRES MN_THREAD = 1, MN_MEMORY = 2, + MN_OBJECT = 3, // MJ_FILESYSTEM MN_SEEKGFAIL = 1, MN_READFAIL = 2, @@ -424,6 +469,8 @@ enum CodeMinor MN_BUSY = 11, MN_XSIZE = 12, MN_EIDINVAL = 13, + MN_EEMPTY = 14, + MN_BUSYPORT = 15, // MJ_AGAIN MN_WRAVAIL = 1, MN_RDAVAIL = 2, @@ -431,12 +478,10 @@ enum CodeMinor MN_CONGESTION = 4 }; -static const enum CodeMinor MN_ISSTREAM SRT_ATR_DEPRECATED = (enum CodeMinor)(9); -static const enum CodeMinor MN_ISDGRAM SRT_ATR_DEPRECATED = (enum CodeMinor)(10); // Stupid, but effective. This will be #undefined, so don't worry. -#define MJ(major) (1000 * MJ_##major) -#define MN(major, minor) (1000 * MJ_##major + MN_##minor) +#define SRT_EMJ(major) (1000 * MJ_##major) +#define SRT_EMN(major, minor) (1000 * MJ_##major + MN_##minor) // Some better way to define it, and better for C language. typedef enum SRT_ERRNO @@ -444,55 +489,56 @@ typedef enum SRT_ERRNO SRT_EUNKNOWN = -1, SRT_SUCCESS = MJ_SUCCESS, - SRT_ECONNSETUP = MJ(SETUP), - SRT_ENOSERVER = MN(SETUP, TIMEOUT), - SRT_ECONNREJ = MN(SETUP, REJECTED), - SRT_ESOCKFAIL = MN(SETUP, NORES), - SRT_ESECFAIL = MN(SETUP, SECURITY), - - SRT_ECONNFAIL = MJ(CONNECTION), - SRT_ECONNLOST = MN(CONNECTION, CONNLOST), - SRT_ENOCONN = MN(CONNECTION, NOCONN), - - SRT_ERESOURCE = MJ(SYSTEMRES), - SRT_ETHREAD = MN(SYSTEMRES, THREAD), - SRT_ENOBUF = MN(SYSTEMRES, MEMORY), - - SRT_EFILE = MJ(FILESYSTEM), - SRT_EINVRDOFF = MN(FILESYSTEM, SEEKGFAIL), - SRT_ERDPERM = MN(FILESYSTEM, READFAIL), - SRT_EINVWROFF = MN(FILESYSTEM, SEEKPFAIL), - SRT_EWRPERM = MN(FILESYSTEM, WRITEFAIL), - - SRT_EINVOP = MJ(NOTSUP), - SRT_EBOUNDSOCK = MN(NOTSUP, ISBOUND), - SRT_ECONNSOCK = MN(NOTSUP, ISCONNECTED), - SRT_EINVPARAM = MN(NOTSUP, INVAL), - SRT_EINVSOCK = MN(NOTSUP, SIDINVAL), - SRT_EUNBOUNDSOCK = MN(NOTSUP, ISUNBOUND), - SRT_ENOLISTEN = MN(NOTSUP, NOLISTEN), - SRT_ERDVNOSERV = MN(NOTSUP, ISRENDEZVOUS), - SRT_ERDVUNBOUND = MN(NOTSUP, ISRENDUNBOUND), - SRT_EINVALMSGAPI = MN(NOTSUP, INVALMSGAPI), - SRT_EINVALBUFFERAPI = MN(NOTSUP, INVALBUFFERAPI), - SRT_EDUPLISTEN = MN(NOTSUP, BUSY), - SRT_ELARGEMSG = MN(NOTSUP, XSIZE), - SRT_EINVPOLLID = MN(NOTSUP, EIDINVAL), - - SRT_EASYNCFAIL = MJ(AGAIN), - SRT_EASYNCSND = MN(AGAIN, WRAVAIL), - SRT_EASYNCRCV = MN(AGAIN, RDAVAIL), - SRT_ETIMEOUT = MN(AGAIN, XMTIMEOUT), - SRT_ECONGEST = MN(AGAIN, CONGESTION), - - SRT_EPEERERR = MJ(PEERERROR) + SRT_ECONNSETUP = SRT_EMJ(SETUP), + SRT_ENOSERVER = SRT_EMN(SETUP, TIMEOUT), + SRT_ECONNREJ = SRT_EMN(SETUP, REJECTED), + SRT_ESOCKFAIL = SRT_EMN(SETUP, NORES), + SRT_ESECFAIL = SRT_EMN(SETUP, SECURITY), + SRT_ESCLOSED = SRT_EMN(SETUP, CLOSED), + + SRT_ECONNFAIL = SRT_EMJ(CONNECTION), + SRT_ECONNLOST = SRT_EMN(CONNECTION, CONNLOST), + SRT_ENOCONN = SRT_EMN(CONNECTION, NOCONN), + + SRT_ERESOURCE = SRT_EMJ(SYSTEMRES), + SRT_ETHREAD = SRT_EMN(SYSTEMRES, THREAD), + SRT_ENOBUF = SRT_EMN(SYSTEMRES, MEMORY), + SRT_ESYSOBJ = SRT_EMN(SYSTEMRES, OBJECT), + + SRT_EFILE = SRT_EMJ(FILESYSTEM), + SRT_EINVRDOFF = SRT_EMN(FILESYSTEM, SEEKGFAIL), + SRT_ERDPERM = SRT_EMN(FILESYSTEM, READFAIL), + SRT_EINVWROFF = SRT_EMN(FILESYSTEM, SEEKPFAIL), + SRT_EWRPERM = SRT_EMN(FILESYSTEM, WRITEFAIL), + + SRT_EINVOP = SRT_EMJ(NOTSUP), + SRT_EBOUNDSOCK = SRT_EMN(NOTSUP, ISBOUND), + SRT_ECONNSOCK = SRT_EMN(NOTSUP, ISCONNECTED), + SRT_EINVPARAM = SRT_EMN(NOTSUP, INVAL), + SRT_EINVSOCK = SRT_EMN(NOTSUP, SIDINVAL), + SRT_EUNBOUNDSOCK = SRT_EMN(NOTSUP, ISUNBOUND), + SRT_ENOLISTEN = SRT_EMN(NOTSUP, NOLISTEN), + SRT_ERDVNOSERV = SRT_EMN(NOTSUP, ISRENDEZVOUS), + SRT_ERDVUNBOUND = SRT_EMN(NOTSUP, ISRENDUNBOUND), + SRT_EINVALMSGAPI = SRT_EMN(NOTSUP, INVALMSGAPI), + SRT_EINVALBUFFERAPI = SRT_EMN(NOTSUP, INVALBUFFERAPI), + SRT_EDUPLISTEN = SRT_EMN(NOTSUP, BUSY), + SRT_ELARGEMSG = SRT_EMN(NOTSUP, XSIZE), + SRT_EINVPOLLID = SRT_EMN(NOTSUP, EIDINVAL), + SRT_EPOLLEMPTY = SRT_EMN(NOTSUP, EEMPTY), + SRT_EBINDCONFLICT = SRT_EMN(NOTSUP, BUSYPORT), + + SRT_EASYNCFAIL = SRT_EMJ(AGAIN), + SRT_EASYNCSND = SRT_EMN(AGAIN, WRAVAIL), + SRT_EASYNCRCV = SRT_EMN(AGAIN, RDAVAIL), + SRT_ETIMEOUT = SRT_EMN(AGAIN, XMTIMEOUT), + SRT_ECONGEST = SRT_EMN(AGAIN, CONGESTION), + + SRT_EPEERERR = SRT_EMJ(PEERERROR) } SRT_ERRNO; -static const SRT_ERRNO SRT_EISSTREAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALMSGAPI); -static const SRT_ERRNO SRT_EISDGRAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, INVALBUFFERAPI); - -#undef MJ -#undef MN +#undef SRT_EMJ +#undef SRT_EMN enum SRT_REJECT_REASON { @@ -510,56 +556,173 @@ enum SRT_REJECT_REASON SRT_REJ_UNSECURE, // password required or unexpected SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision SRT_REJ_CONGESTION, // incompatible congestion-controller type - SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_GROUP, // incompatible group + SRT_REJ_TIMEOUT, // connection timeout +#ifdef ENABLE_AEAD_API_PREVIEW + SRT_REJ_CRYPTO, // conflicting cryptographic configurations +#endif - SRT_REJ__SIZE, + SRT_REJ_E_SIZE, }; +// XXX This value remains for some time, but it's deprecated +// Planned deprecation removal: rel1.6.0. +#define SRT_REJ__SIZE SRT_REJ_E_SIZE + +// Reject category codes: + +#define SRT_REJC_VALUE(code) (1000 * (code/1000)) +#define SRT_REJC_INTERNAL 0 // Codes from above SRT_REJECT_REASON enum +#define SRT_REJC_PREDEFINED 1000 // Standard server error codes +#define SRT_REJC_USERDEFINED 2000 // User defined error codes + + // Logging API - specialization for SRT. -// Define logging functional areas for log selection. -// Use values greater than 0. Value 0 is reserved for LOGFA_GENERAL, -// which is considered always enabled. +// WARNING: This part is generated. // Logger Functional Areas // Note that 0 is "general". +// Values 0* - general, unqualified +// Values 1* - control +// Values 2* - receiving +// Values 3* - sending +// Values 4* - management + // Made by #define so that it's available also for C API. -#define SRT_LOGFA_GENERAL 0 -#define SRT_LOGFA_BSTATS 1 -#define SRT_LOGFA_CONTROL 2 -#define SRT_LOGFA_DATA 3 -#define SRT_LOGFA_TSBPD 4 -#define SRT_LOGFA_REXMIT 5 -#define SRT_LOGFA_HAICRYPT 6 -#define SRT_LOGFA_CONGEST 7 - -// To make a typical int32_t size, although still use std::bitset. + +// Use ../scripts/generate-logging-defs.tcl to regenerate. + +// SRT_LOGFA BEGIN GENERATED SECTION { + +#define SRT_LOGFA_GENERAL 0 // gglog: General uncategorized log, for serious issues only +#define SRT_LOGFA_SOCKMGMT 1 // smlog: Socket create/open/close/configure activities +#define SRT_LOGFA_CONN 2 // cnlog: Connection establishment and handshake +#define SRT_LOGFA_XTIMER 3 // xtlog: The checkTimer and around activities +#define SRT_LOGFA_TSBPD 4 // tslog: The TsBPD thread +#define SRT_LOGFA_RSRC 5 // rslog: System resource allocation and management + +#define SRT_LOGFA_CONGEST 7 // cclog: Congestion control module +#define SRT_LOGFA_PFILTER 8 // pflog: Packet filter module + +#define SRT_LOGFA_API_CTRL 11 // aclog: API part for socket and library managmenet + +#define SRT_LOGFA_QUE_CTRL 13 // qclog: Queue control activities + +#define SRT_LOGFA_EPOLL_UPD 16 // eilog: EPoll, internal update activities + +#define SRT_LOGFA_API_RECV 21 // arlog: API part for receiving +#define SRT_LOGFA_BUF_RECV 22 // brlog: Buffer, receiving side +#define SRT_LOGFA_QUE_RECV 23 // qrlog: Queue, receiving side +#define SRT_LOGFA_CHN_RECV 24 // krlog: CChannel, receiving side +#define SRT_LOGFA_GRP_RECV 25 // grlog: Group, receiving side + +#define SRT_LOGFA_API_SEND 31 // aslog: API part for sending +#define SRT_LOGFA_BUF_SEND 32 // bslog: Buffer, sending side +#define SRT_LOGFA_QUE_SEND 33 // qslog: Queue, sending side +#define SRT_LOGFA_CHN_SEND 34 // kslog: CChannel, sending side +#define SRT_LOGFA_GRP_SEND 35 // gslog: Group, sending side + +#define SRT_LOGFA_INTERNAL 41 // inlog: Internal activities not connected directly to a socket + +#define SRT_LOGFA_QUE_MGMT 43 // qmlog: Queue, management part +#define SRT_LOGFA_CHN_MGMT 44 // kmlog: CChannel, management part +#define SRT_LOGFA_GRP_MGMT 45 // gmlog: Group, management part +#define SRT_LOGFA_EPOLL_API 46 // ealog: EPoll, API part + +#define SRT_LOGFA_HAICRYPT 6 // hclog: Haicrypt module area +#define SRT_LOGFA_APPLOG 10 // aplog: Applications + +// } SRT_LOGFA END GENERATED SECTION + +// To make a typical int64_t size, although still use std::bitset. // C API will carry it over. -#define SRT_LOGFA_LASTNONE 31 +#define SRT_LOGFA_LASTNONE 63 enum SRT_KM_STATE { - SRT_KM_S_UNSECURED = 0, //No encryption - SRT_KM_S_SECURING = 1, //Stream encrypted, exchanging Keying Material - SRT_KM_S_SECURED = 2, //Stream encrypted, keying Material exchanged, decrypting ok. - SRT_KM_S_NOSECRET = 3, //Stream encrypted and no secret to decrypt Keying Material - SRT_KM_S_BADSECRET = 4 //Stream encrypted and wrong secret, cannot decrypt Keying Material + SRT_KM_S_UNSECURED = 0, // No encryption + SRT_KM_S_SECURING = 1, // Stream encrypted, exchanging Keying Material + SRT_KM_S_SECURED = 2, // Stream encrypted, keying Material exchanged, decrypting ok. + SRT_KM_S_NOSECRET = 3, // Stream encrypted and no secret to decrypt Keying Material + SRT_KM_S_BADSECRET = 4 // Stream encrypted and wrong secret is used, cannot decrypt Keying Material +#ifdef ENABLE_AEAD_API_PREVIEW + ,SRT_KM_S_BADCRYPTOMODE = 5 // Stream encrypted but wrong cryptographic mode is used, cannot decrypt. Since v1.5.2. +#endif }; enum SRT_EPOLL_OPT { SRT_EPOLL_OPT_NONE = 0x0, // fallback - // this values are defined same as linux epoll.h + + // Values intended to be the same as in ``. // so that if system values are used by mistake, they should have the same effect + // This applies to: IN, OUT, ERR and ET. + + /// Ready for 'recv' operation: + /// + /// - For stream mode it means that at least 1 byte is available. + /// In this mode the buffer may extract only a part of the packet, + /// leaving next data possible for extraction later. + /// + /// - For message mode it means that there is at least one packet + /// available (this may change in future, as it is desired that + /// one full message should only wake up, not single packet of a + /// not yet extractable message). + /// + /// - For live mode it means that there's at least one packet + /// ready to play. + /// + /// - For listener sockets, this means that there is a new connection + /// waiting for pickup through the `srt_accept()` call, that is, + /// the next call to `srt_accept()` will succeed without blocking + /// (see an alias SRT_EPOLL_ACCEPT below). SRT_EPOLL_IN = 0x1, + + /// Ready for 'send' operation. + /// + /// - For stream mode it means that there's a free space in the + /// sender buffer for at least 1 byte of data. The next send + /// operation will only allow to send as much data as it is free + /// space in the buffer. + /// + /// - For message mode it means that there's a free space for at + /// least one UDP packet. The edge-triggered mode can be used to + /// pick up updates as the free space in the sender buffer grows. + /// + /// - For live mode it means that there's a free space for at least + /// one UDP packet. On the other hand, no readiness for OUT usually + /// means an extraordinary congestion on the link, meaning also that + /// you should immediately slow down the sending rate or you may get + /// a connection break soon. + /// + /// - For non-blocking sockets used with `srt_connect*` operation, + /// this flag simply means that the connection was established. SRT_EPOLL_OUT = 0x4, + + /// The socket has encountered an error in the last operation + /// and the next operation on that socket will end up with error. + /// You can retry the operation, but getting the error from it + /// is certain, so you may as well close the socket. SRT_EPOLL_ERR = 0x8, + + // To avoid confusion in the internal code, the following + // duplicates are introduced to improve clarity. + SRT_EPOLL_CONNECT = SRT_EPOLL_OUT, + SRT_EPOLL_ACCEPT = SRT_EPOLL_IN, + + SRT_EPOLL_UPDATE = 0x10, SRT_EPOLL_ET = 1u << 31 }; // These are actually flags - use a bit container: typedef int32_t SRT_EPOLL_T; +// Define which epoll flags determine events. All others are special flags. +#define SRT_EPOLL_EVENTTYPES (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_UPDATE | SRT_EPOLL_ERR) +#define SRT_EPOLL_ETONLY (SRT_EPOLL_UPDATE) + enum SRT_EPOLL_FLAGS { /// This allows the EID container to be empty when calling the waiting @@ -582,17 +745,8 @@ inline SRT_EPOLL_OPT operator|(SRT_EPOLL_OPT a1, SRT_EPOLL_OPT a2) return SRT_EPOLL_OPT( (int)a1 | (int)a2 ); } -inline bool operator&(int flags, SRT_EPOLL_OPT eflg) -{ - // Using an enum prevents treating int automatically as enum, - // requires explicit enum to be passed here, and minimizes the - // risk that the right side value will contain multiple flags. - return (flags & int(eflg)) != 0; -} #endif - - typedef struct CBytePerfMon SRT_TRACEBSTATS; static const SRTSOCKET SRT_INVALID_SOCK = -1; @@ -605,18 +759,32 @@ SRT_API int srt_cleanup(void); // // Socket operations // -SRT_API SRTSOCKET srt_socket (int af, int type, int protocol); -SRT_API SRTSOCKET srt_create_socket(); +// DEPRECATED: srt_socket with 3 arguments. All these arguments are ignored +// and socket creation doesn't need any arguments. Use srt_create_socket(). +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX SRT_API SRTSOCKET srt_socket(int, int, int) SRT_ATR_DEPRECATED; +SRT_API SRTSOCKET srt_create_socket(void); + SRT_API int srt_bind (SRTSOCKET u, const struct sockaddr* name, int namelen); -SRT_API int srt_bind_peerof (SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int srt_bind_acquire (SRTSOCKET u, UDPSOCKET sys_udp_sock); +// Old name of srt_bind_acquire(), please don't use +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX static inline int srt_bind_peerof(SRTSOCKET u, UDPSOCKET sys_udp_sock) SRT_ATR_DEPRECATED; +static inline int srt_bind_peerof (SRTSOCKET u, UDPSOCKET sys_udp_sock) { return srt_bind_acquire(u, sys_udp_sock); } SRT_API int srt_listen (SRTSOCKET u, int backlog); SRT_API SRTSOCKET srt_accept (SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API SRTSOCKET srt_accept_bond (const SRTSOCKET listeners[], int lsize, int64_t msTimeOut); typedef int srt_listen_callback_fn (void* opaq, SRTSOCKET ns, int hsversion, const struct sockaddr* peeraddr, const char* streamid); SRT_API int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); +typedef void srt_connect_callback_fn (void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); +SRT_API int srt_connect_callback(SRTSOCKET clr, srt_connect_callback_fn* hook_fn, void* hook_opaque); SRT_API int srt_connect (SRTSOCKET u, const struct sockaddr* name, int namelen); SRT_API int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +SRT_API int srt_connect_bind (SRTSOCKET u, const struct sockaddr* source, + const struct sockaddr* target, int len); SRT_API int srt_rendezvous (SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, const struct sockaddr* remote_name, int remote_namelen); + SRT_API int srt_close (SRTSOCKET u); SRT_API int srt_getpeername (SRTSOCKET u, struct sockaddr* name, int* namelen); SRT_API int srt_getsockname (SRTSOCKET u, struct sockaddr* name, int* namelen); @@ -625,19 +793,34 @@ SRT_API int srt_setsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCK SRT_API int srt_getsockflag (SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); SRT_API int srt_setsockflag (SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); +typedef struct SRT_SocketGroupData_ SRT_SOCKGROUPDATA; -// XXX Note that the srctime functionality doesn't work yet and needs fixing. typedef struct SRT_MsgCtrl_ { int flags; // Left for future - int msgttl; // TTL for a message, default -1 (no TTL limitation) + int msgttl; // TTL for a message (millisec), default -1 (no TTL limitation) int inorder; // Whether a message is allowed to supersede partially lost one. Unused in stream and live mode. int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame - uint64_t srctime; // source timestamp (usec), 0: use internal time + int64_t srctime; // source time since epoch (usec), 0: use internal time (sender) int32_t pktseq; // sequence number of the first packet in received message (unused for sending) int32_t msgno; // message number (output value for both sending and receiving) + SRT_SOCKGROUPDATA* grpdata; + size_t grpdata_size; } SRT_MSGCTRL; +// Trap representation for sequence and message numbers +// This value means that this is "unset", and it's never +// a result of an operation made on this number. +static const int32_t SRT_SEQNO_NONE = -1; // -1: no seq (0 is a valid seqno!) +static const int32_t SRT_MSGNO_NONE = -1; // -1: unset +static const int32_t SRT_MSGNO_CONTROL = 0; // 0: control (used by packet filter) + +static const int SRT_MSGTTL_INF = -1; // unlimited TTL specification for message TTL + +// XXX Might be useful also other special uses of -1: +// - -1 as infinity for srt_epoll_wait +// - -1 as a trap index value used in list.cpp + // You are free to use either of these two methods to set SRT_MSGCTRL object // to default values: either call srt_msgctrl_init(&obj) or obj = srt_msgctrl_default. SRT_API void srt_msgctrl_init(SRT_MSGCTRL* mctrl); @@ -657,11 +840,6 @@ SRT_API extern const SRT_MSGCTRL srt_msgctrl_default; // parameters will be filled, as needed. NULL is acceptable, in which case // the defaults are used. -// NOTE: srt_send and srt_recv have the last "..." left to allow ignore a -// deprecated and unused "flags" parameter. After confirming that all -// compat applications that pass useless 0 there are fixed, this will be -// removed. - // // Sending functions // @@ -692,16 +870,17 @@ SRT_API int srt_getlasterror(int* errno_loc); SRT_API const char* srt_strerror(int code, int errnoval); SRT_API void srt_clearlasterror(void); -// performance track -// perfmon with Byte counters for better bitrate estimation. +// Performance tracking +// Performance monitor with Byte counters for better bitrate estimation. SRT_API int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); -// permon with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. +// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. SRT_API int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); // Socket Status (for problem tracking) SRT_API SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); SRT_API int srt_epoll_create(void); +SRT_API int srt_epoll_clear_usocks(int eid); SRT_API int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); SRT_API int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_remove_usock(int eid, SRTSOCKET u); @@ -711,10 +890,14 @@ SRT_API int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); SRT_API int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); -typedef struct SRT_EPOLL_EVENT_ +typedef struct SRT_EPOLL_EVENT_STR { SRTSOCKET fd; int events; // SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR +#ifdef __cplusplus + SRT_EPOLL_EVENT_STR(SRTSOCKET s, int ev): fd(s), events(ev) {} + SRT_EPOLL_EVENT_STR(): fd(-1), events(0) {} // NOTE: allows singular values, no init. +#endif } SRT_EPOLL_EVENT; SRT_API int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); @@ -736,9 +919,88 @@ SRT_API void srt_setlogflags(int flags); SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); -SRT_API enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); -SRT_API extern const char* const srt_rejectreason_msg []; -const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); +SRT_API int srt_getrejectreason(SRTSOCKET sock); +SRT_API int srt_setrejectreason(SRTSOCKET sock, int value); +// The srt_rejectreason_msg[] array is deprecated (as unsafe). +// Planned removal: v1.6.0. +SRT_API SRT_ATR_DEPRECATED extern const char* const srt_rejectreason_msg []; +SRT_API const char* srt_rejectreason_str(int id); + +SRT_API uint32_t srt_getversion(void); + +SRT_API int64_t srt_time_now(void); + +SRT_API int64_t srt_connection_time(SRTSOCKET sock); + +// Possible internal clock types +#define SRT_SYNC_CLOCK_STDCXX_STEADY 0 // C++11 std::chrono::steady_clock +#define SRT_SYNC_CLOCK_GETTIME_MONOTONIC 1 // clock_gettime with CLOCK_MONOTONIC +#define SRT_SYNC_CLOCK_WINQPC 2 +#define SRT_SYNC_CLOCK_MACH_ABSTIME 3 +#define SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY 4 +#define SRT_SYNC_CLOCK_AMD64_RDTSC 5 +#define SRT_SYNC_CLOCK_IA32_RDTSC 6 +#define SRT_SYNC_CLOCK_IA64_ITC 7 + +SRT_API int srt_clock_type(void); + +// SRT Socket Groups API (ENABLE_BONDING) + +typedef enum SRT_GROUP_TYPE +{ + SRT_GTYPE_UNDEFINED, + SRT_GTYPE_BROADCAST, + SRT_GTYPE_BACKUP, + // ... + SRT_GTYPE_E_END +} SRT_GROUP_TYPE; + +// Free-form flags for groups +// Flags may be type-specific! +static const uint32_t SRT_GFLAG_SYNCONMSG = 1; + +typedef enum SRT_MemberStatus +{ + SRT_GST_PENDING, // The socket is created correctly, but not yet ready for getting data. + SRT_GST_IDLE, // The socket is ready to be activated + SRT_GST_RUNNING, // The socket was already activated and is in use + SRT_GST_BROKEN // The last operation broke the socket, it should be closed. +} SRT_MEMBERSTATUS; + +struct SRT_SocketGroupData_ +{ + SRTSOCKET id; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + SRT_SOCKSTATUS sockstate; + uint16_t weight; + SRT_MEMBERSTATUS memberstate; + int result; + int token; +}; + +typedef struct SRT_SocketOptionObject SRT_SOCKOPT_CONFIG; + +typedef struct SRT_GroupMemberConfig_ +{ + SRTSOCKET id; + struct sockaddr_storage srcaddr; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + uint16_t weight; + SRT_SOCKOPT_CONFIG* config; + int errorcode; + int token; +} SRT_SOCKGROUPCONFIG; + +SRT_API SRTSOCKET srt_create_group(SRT_GROUP_TYPE); +SRT_API SRTSOCKET srt_groupof(SRTSOCKET socket); +SRT_API int srt_group_data(SRTSOCKET socketgroup, SRT_SOCKGROUPDATA* output, size_t* inoutlen); + +SRT_API SRT_SOCKOPT_CONFIG* srt_create_config(void); +SRT_API void srt_delete_config(SRT_SOCKOPT_CONFIG* config /*nullable*/); +SRT_API int srt_config_add(SRT_SOCKOPT_CONFIG* config, SRT_SOCKOPT option, const void* contents, int len); + +SRT_API SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, const struct sockaddr* adr, int namelen); +SRT_API int srt_connect_group(SRTSOCKET group, SRT_SOCKGROUPCONFIG name[], int arraysize); #ifdef __cplusplus } diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt4udt.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt4udt.h deleted file mode 100644 index 49f6d9f7a..000000000 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt4udt.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SRT - Secure, Reliable, Transport - * Copyright (c) 2018 Haivision Systems Inc. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -/***************************************************************************** -written by - Haivision Systems Inc. - *****************************************************************************/ - -#ifndef SRT4UDT_H -#define SRT4UDT_H - -#ifndef INC__SRTC_H -#error "This is protected header, used by udt.h. This shouldn't be included directly" -#endif - -//undef SRT_ENABLE_ECN 1 /* Early Congestion Notification (for source bitrate control) */ - -//undef SRT_DEBUG_TSBPD_OUTJITTER 1 /* Packet Delivery histogram */ -//undef SRT_DEBUG_TSBPD_DRIFT 1 /* Debug Encoder-Decoder Drift) */ -//undef SRT_DEBUG_TSBPD_WRAP 1 /* Debug packet timestamp wraparound */ -//undef SRT_DEBUG_TLPKTDROP_DROPSEQ 1 -//undef SRT_DEBUG_SNDQ_HIGHRATE 1 - - -/* -* SRT_ENABLE_CONNTIMEO -* Option UDT_CONNTIMEO added to the API to set/get the connection timeout. -* The UDT hard coded default of 3000 msec is too small for some large RTT (satellite) use cases. -* The SRT handshake (2 exchanges) needs 2 times the RTT to complete with no packet loss. -*/ -#define SRT_ENABLE_CONNTIMEO 1 - -/* -* SRT_ENABLE_NOCWND -* Set the congestion window at its max (then disabling it) to prevent stopping transmission -* when too many packets are not acknowledged. -* The congestion windows is the maximum distance in pkts since the last acknowledged packets. -*/ -#define SRT_ENABLE_NOCWND 1 - -/* -* SRT_ENABLE_NAKREPORT -* Send periodic NAK report for more efficient retransmission instead of relying on ACK timeout -* to retransmit all non-ACKed packets, very inefficient with real-time and no congestion window. -*/ -#define SRT_ENABLE_NAKREPORT 1 - -#define SRT_ENABLE_RCVBUFSZ_MAVG 1 /* Recv buffer size moving average */ -#define SRT_ENABLE_SNDBUFSZ_MAVG 1 /* Send buffer size moving average */ -#define SRT_MAVG_SAMPLING_RATE 40 /* Max sampling rate */ - -#define SRT_ENABLE_LOSTBYTESCOUNT 1 - - -/* -* SRT_ENABLE_IPOPTS -* Enable IP TTL and ToS setting -*/ -#define SRT_ENABLE_IPOPTS 1 - - -#define SRT_ENABLE_CLOSE_SYNCH 1 - -#endif /* SRT4UDT_H */ diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_attr_defs.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_attr_defs.h new file mode 100644 index 000000000..84daabeb1 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_attr_defs.h @@ -0,0 +1,191 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v.2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +/***************************************************************************** +The file contains various planform and compiler dependent attribute definitions +used by SRT library internally. + *****************************************************************************/ + +#ifndef INC_SRT_ATTR_DEFS_H +#define INC_SRT_ATTR_DEFS_H + +// ATTRIBUTES: +// +// SRT_ATR_UNUSED: declare an entity ALLOWED to be unused (prevents warnings) +// ATR_DEPRECATED: declare an entity deprecated (compiler should warn when used) +// ATR_NOEXCEPT: The true `noexcept` from C++11, or nothing if compiling in pre-C++11 mode +// ATR_NOTHROW: In C++11: `noexcept`. In pre-C++11: `throw()`. Required for GNU libstdc++. +// ATR_CONSTEXPR: In C++11: `constexpr`. Otherwise empty. +// ATR_OVERRIDE: In C++11: `override`. Otherwise empty. +// ATR_FINAL: In C++11: `final`. Otherwise empty. + +#ifdef __GNUG__ +#define ATR_DEPRECATED __attribute__((deprecated)) +#else +#define ATR_DEPRECATED +#endif + +#if defined(__cplusplus) && __cplusplus > 199711L +#define HAVE_CXX11 1 +// For gcc 4.7, claim C++11 is supported, as long as experimental C++0x is on, +// however it's only the "most required C++11 support". +#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 // 4.7 only! +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#else +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1800 +// Microsoft Visual Studio supports C++11, but not fully, +// and still did not change the value of __cplusplus. Treat +// this special way. +// _MSC_VER == 1800 means Microsoft Visual Studio 2013. +#define HAVE_CXX11 1 +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 +#define HAVE_FULL_CXX11 1 +#define ATR_NOEXCEPT noexcept +#define ATR_NOTHROW noexcept +#define ATR_CONSTEXPR constexpr +#define ATR_OVERRIDE override +#define ATR_FINAL final +#else +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif +#else +#define HAVE_CXX11 0 +#define ATR_NOEXCEPT +#define ATR_NOTHROW throw() +#define ATR_CONSTEXPR +#define ATR_OVERRIDE +#define ATR_FINAL +#endif // __cplusplus + +#if !HAVE_CXX11 && defined(REQUIRE_CXX11) && REQUIRE_CXX11 == 1 +#error "The currently compiled application required C++11, but your compiler doesn't support it." +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Attributes for thread safety analysis +// - Clang TSA (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutexheader). +// - MSVC SAL (partially). +// - Other compilers: none. +/////////////////////////////////////////////////////////////////////////////// +#if _MSC_VER >= 1920 +// In case of MSVC these attributes have to precede the attributed objects (variable, function). +// E.g. SRT_ATTR_GUARDED_BY(mtx) int object; +// It is tricky to annotate e.g. the following function, as clang complaints it does not know 'm'. +// SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) +// inline void enterCS(Mutex& m) { m.lock(); } +#define SRT_ATTR_CAPABILITY(expr) +#define SRT_ATTR_SCOPED_CAPABILITY +#define SRT_ATTR_GUARDED_BY(expr) _Guarded_by_(expr) +#define SRT_ATTR_PT_GUARDED_BY(expr) +#define SRT_ATTR_ACQUIRED_BEFORE(...) +#define SRT_ATTR_ACQUIRED_AFTER(...) +#define SRT_ATTR_REQUIRES(expr) _Requires_lock_held_(expr) +#define SRT_ATTR_REQUIRES2(expr1, expr2) _Requires_lock_held_(expr1) _Requires_lock_held_(expr2) +#define SRT_ATTR_REQUIRES_SHARED(...) +#define SRT_ATTR_ACQUIRE(expr) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_ACQUIRE_SHARED(...) +#define SRT_ATTR_RELEASE(expr) _Releases_lock_(expr) +#define SRT_ATTR_RELEASE_SHARED(...) +#define SRT_ATTR_RELEASE_GENERIC(...) +#define SRT_ATTR_TRY_ACQUIRE(...) _Acquires_nonreentrant_lock_(expr) +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) +#define SRT_ATTR_EXCLUDES(...) +#define SRT_ATTR_ASSERT_CAPABILITY(expr) +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) +#define SRT_ATTR_RETURN_CAPABILITY(x) +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS +#else + +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define SRT_ATTR_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SRT_ATTR_SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define SRT_ATTR_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define SRT_ATTR_PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define SRT_ATTR_ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES2(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SRT_ATTR_REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_RELEASE_GENERIC(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define SRT_ATTR_EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define SRT_ATTR_ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define SRT_ATTR_RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // not _MSC_VER + +#endif // INC_SRT_ATTR_DEFS_H diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_compat.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_compat.h new file mode 100644 index 000000000..960c1b85a --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/srt_compat.h @@ -0,0 +1,109 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_COMPAT_H +#define INC_SRT_COMPAT_H + +#include +#include + +#ifndef SRT_API +#ifdef _WIN32 + #ifndef __MINGW32__ + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) + #else + #define SRT_API __declspec(dllimport) + #endif + #else + #define SRT_API + #endif + #else + #define SRT_API + #endif +#else + #define SRT_API __attribute__ ((visibility("default"))) +#endif +#endif + +#ifdef _WIN32 + // https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "Id" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "Iu" + #endif +#else + // http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html + // printf() Format for ssize_t + #if !defined(PRIzd) + #define PRIzd "zd" + #endif + // printf() Format for size_t + #if !defined(PRIzu) + #define PRIzu "zu" + #endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Ensures that we store the error in the buffer and return the bufer. */ +SRT_API const char * SysStrError(int errnum, char * buf, size_t buflen); + +#ifdef __cplusplus +} // extern C + + +// Extra C++ stuff. Included only in C++ mode. + + +#include +#include +inline std::string SysStrError(int errnum) +{ + char buf[1024]; + return SysStrError(errnum, buf, 1024); +} + +inline struct tm SysLocalTime(time_t tt) +{ + struct tm tms; + memset(&tms, 0, sizeof tms); +#ifdef _WIN32 + errno_t rr = localtime_s(&tms, &tt); + if (rr == 0) + return tms; +#else + + // Ignore the error, state that if something + // happened, you simply have a pre-cleared tms. + localtime_r(&tt, &tms); +#endif + + return tms; +} + + +#endif // defined C++ + +#endif // INC_SRT_COMPAT_H diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/stats.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/stats.h new file mode 100644 index 000000000..bce60761b --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/stats.h @@ -0,0 +1,221 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_STATS_H +#define INC_SRT_STATS_H + +#include "platform_sys.h" +#include "packet.h" + +namespace srt +{ +namespace stats +{ + +class Packets +{ +public: + Packets() : m_count(0) {} + + Packets(uint32_t num) : m_count(num) {} + + void reset() + { + m_count = 0; + } + + Packets& operator+= (const Packets& other) + { + m_count += other.m_count; + return *this; + } + + uint32_t count() const + { + return m_count; + } + +private: + uint32_t m_count; +}; + +class BytesPackets +{ +public: + BytesPackets() + : m_bytes(0) + , m_packets(0) + {} + + BytesPackets(uint64_t bytes, uint32_t n = 1) + : m_bytes(bytes) + , m_packets(n) + {} + + BytesPackets& operator+= (const BytesPackets& other) + { + m_bytes += other.m_bytes; + m_packets += other.m_packets; + return *this; + } + +public: + void reset() + { + m_packets = 0; + m_bytes = 0; + } + + void count(uint64_t bytes, size_t n = 1) + { + m_packets += (uint32_t) n; + m_bytes += bytes; + } + + uint64_t bytes() const + { + return m_bytes; + } + + uint32_t count() const + { + return m_packets; + } + + uint64_t bytesWithHdr() const + { + return m_bytes + m_packets * CPacket::SRT_DATA_HDR_SIZE; + } + +private: + uint64_t m_bytes; + uint32_t m_packets; +}; + +template +struct Metric +{ + METRIC_TYPE trace; + METRIC_TYPE total; + + void count(METRIC_TYPE val) + { + trace += val; + total += val; + } + + void reset() + { + trace.reset(); + total.reset(); + } + + void resetTrace() + { + trace.reset(); + } +}; + +/// Sender-side statistics. +struct Sender +{ + Metric sent; + Metric sentUnique; + Metric sentRetrans; // The number of data packets retransmitted by the sender. + Metric lost; // The number of packets reported lost (including repeated reports) to the sender in NAKs. + Metric dropped; // The number of data packets dropped by the sender. + + Metric sentFilterExtra; // The number of packets generate by the packet filter and sent by the sender. + + Metric recvdAck; // The number of ACK packets received by the sender. + Metric recvdNak; // The number of ACK packets received by the sender. + + void reset() + { + sent.reset(); + sentUnique.reset(); + sentRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdAck.reset(); + recvdNak.reset(); + sentFilterExtra.reset(); + } + + void resetTrace() + { + sent.resetTrace(); + sentUnique.resetTrace(); + sentRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdAck.resetTrace(); + recvdNak.resetTrace(); + sentFilterExtra.resetTrace(); + } +}; + +/// Receiver-side statistics. +struct Receiver +{ + Metric recvd; + Metric recvdUnique; + Metric recvdRetrans; // The number of retransmitted data packets received by the receiver. + Metric lost; // The number of packets detected by the receiver as lost. + Metric dropped; // The number of packets dropped by the receiver (as too-late to be delivered). + Metric recvdBelated; // The number of belated packets received (dropped as too late but eventually received). + Metric undecrypted; // The number of packets received by the receiver that failed to be decrypted. + + Metric recvdFilterExtra; // The number of filter packets (e.g. FEC) received by the receiver. + Metric suppliedByFilter; // The number of lost packets got from the packet filter at the receiver side (e.g. loss recovered by FEC). + Metric lossFilter; // The number of lost DATA packets not recovered by the packet filter at the receiver side. + + Metric sentAck; // The number of ACK packets sent by the receiver. + Metric sentNak; // The number of NACK packets sent by the receiver. + + void reset() + { + recvd.reset(); + recvdUnique.reset(); + recvdRetrans.reset(); + lost.reset(); + dropped.reset(); + recvdBelated.reset(); + undecrypted.reset(); + recvdFilterExtra.reset(); + suppliedByFilter.reset(); + lossFilter.reset(); + sentAck.reset(); + sentNak.reset(); + } + + void resetTrace() + { + recvd.resetTrace(); + recvdUnique.resetTrace(); + recvdRetrans.resetTrace(); + lost.resetTrace(); + dropped.resetTrace(); + recvdBelated.resetTrace(); + undecrypted.resetTrace(); + recvdFilterExtra.resetTrace(); + suppliedByFilter.resetTrace(); + lossFilter.resetTrace(); + sentAck.resetTrace(); + sentNak.resetTrace(); + } +}; + +} // namespace stats +} // namespace srt + +#endif // INC_SRT_STATS_H + + diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/sync.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/sync.h new file mode 100644 index 000000000..87be6f458 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/sync.h @@ -0,0 +1,947 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +#pragma once +#ifndef INC_SRT_SYNC_H +#define INC_SRT_SYNC_H + +#include "platform_sys.h" + +#include +#include +#ifdef ENABLE_STDCXX_SYNC +#include +#include +#include +#include +#include +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_STDCXX_STEADY +#define SRT_SYNC_CLOCK_STR "STDCXX_STEADY" +#else +#include + +// Defile clock type to use +#ifdef IA32 +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA32_RDTSC +#define SRT_SYNC_CLOCK_STR "IA32_RDTSC" +#elif defined(IA64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA64_ITC +#define SRT_SYNC_CLOCK_STR "IA64_ITC" +#elif defined(AMD64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_AMD64_RDTSC +#define SRT_SYNC_CLOCK_STR "AMD64_RDTSC" +#elif defined(_WIN32) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_WINQPC +#define SRT_SYNC_CLOCK_STR "WINQPC" +#elif TARGET_OS_MAC +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_MACH_ABSTIME +#define SRT_SYNC_CLOCK_STR "MACH_ABSTIME" +#elif defined(ENABLE_MONOTONIC_CLOCK) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_GETTIME_MONOTONIC +#define SRT_SYNC_CLOCK_STR "GETTIME_MONOTONIC" +#else +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY +#define SRT_SYNC_CLOCK_STR "POSIX_GETTIMEOFDAY" +#endif + +#endif // ENABLE_STDCXX_SYNC + +#include "srt.h" +#include "utilities.h" +#include "srt_attr_defs.h" + + +namespace srt +{ + +class CUDTException; // defined in common.h + +namespace sync +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration class +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +template +using Duration = std::chrono::duration; + +#else + +/// Class template srt::sync::Duration represents a time interval. +/// It consists of a count of ticks of _Clock. +/// It is a wrapper of system timers in case of non-C++11 chrono build. +template +class Duration +{ +public: + Duration() + : m_duration(0) + { + } + + explicit Duration(int64_t d) + : m_duration(d) + { + } + +public: + inline int64_t count() const { return m_duration; } + + static Duration zero() { return Duration(); } + +public: // Relational operators + inline bool operator>=(const Duration& rhs) const { return m_duration >= rhs.m_duration; } + inline bool operator>(const Duration& rhs) const { return m_duration > rhs.m_duration; } + inline bool operator==(const Duration& rhs) const { return m_duration == rhs.m_duration; } + inline bool operator!=(const Duration& rhs) const { return m_duration != rhs.m_duration; } + inline bool operator<=(const Duration& rhs) const { return m_duration <= rhs.m_duration; } + inline bool operator<(const Duration& rhs) const { return m_duration < rhs.m_duration; } + +public: // Assignment operators + inline void operator*=(const int64_t mult) { m_duration = static_cast(m_duration * mult); } + inline void operator+=(const Duration& rhs) { m_duration += rhs.m_duration; } + inline void operator-=(const Duration& rhs) { m_duration -= rhs.m_duration; } + + inline Duration operator+(const Duration& rhs) const { return Duration(m_duration + rhs.m_duration); } + inline Duration operator-(const Duration& rhs) const { return Duration(m_duration - rhs.m_duration); } + inline Duration operator*(const int64_t& rhs) const { return Duration(m_duration * rhs); } + inline Duration operator/(const int64_t& rhs) const { return Duration(m_duration / rhs); } + +private: + // int64_t range is from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 + int64_t m_duration; +}; + +#endif // ENABLE_STDCXX_SYNC + +/////////////////////////////////////////////////////////////////////////////// +// +// TimePoint and steadt_clock classes +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC + +using steady_clock = std::chrono::steady_clock; + +template +using time_point = std::chrono::time_point; + +template +using TimePoint = std::chrono::time_point; + +template +inline bool is_zero(const time_point &tp) +{ + return tp.time_since_epoch() == Clock::duration::zero(); +} + +inline bool is_zero(const steady_clock::time_point& t) +{ + return t == steady_clock::time_point(); +} + +#else +template +class TimePoint; + +class steady_clock +{ +public: + typedef Duration duration; + typedef TimePoint time_point; + +public: + static time_point now(); +}; + +/// Represents a point in time +template +class TimePoint +{ +public: + TimePoint() + : m_timestamp(0) + { + } + + explicit TimePoint(uint64_t tp) + : m_timestamp(tp) + { + } + + TimePoint(const TimePoint& other) + : m_timestamp(other.m_timestamp) + { + } + + TimePoint(const Duration& duration_since_epoch) + : m_timestamp(duration_since_epoch.count()) + { + } + + ~TimePoint() {} + +public: // Relational operators + inline bool operator<(const TimePoint& rhs) const { return m_timestamp < rhs.m_timestamp; } + inline bool operator<=(const TimePoint& rhs) const { return m_timestamp <= rhs.m_timestamp; } + inline bool operator==(const TimePoint& rhs) const { return m_timestamp == rhs.m_timestamp; } + inline bool operator!=(const TimePoint& rhs) const { return m_timestamp != rhs.m_timestamp; } + inline bool operator>=(const TimePoint& rhs) const { return m_timestamp >= rhs.m_timestamp; } + inline bool operator>(const TimePoint& rhs) const { return m_timestamp > rhs.m_timestamp; } + +public: // Arithmetic operators + inline Duration operator-(const TimePoint& rhs) const + { + return Duration(m_timestamp - rhs.m_timestamp); + } + inline TimePoint operator+(const Duration& rhs) const { return TimePoint(m_timestamp + rhs.count()); } + inline TimePoint operator-(const Duration& rhs) const { return TimePoint(m_timestamp - rhs.count()); } + +public: // Assignment operators + inline void operator=(const TimePoint& rhs) { m_timestamp = rhs.m_timestamp; } + inline void operator+=(const Duration& rhs) { m_timestamp += rhs.count(); } + inline void operator-=(const Duration& rhs) { m_timestamp -= rhs.count(); } + +public: // + static inline ATR_CONSTEXPR TimePoint min() { return TimePoint(std::numeric_limits::min()); } + static inline ATR_CONSTEXPR TimePoint max() { return TimePoint(std::numeric_limits::max()); } + +public: + Duration time_since_epoch() const; + +private: + uint64_t m_timestamp; +}; + +template <> +srt::sync::Duration srt::sync::TimePoint::time_since_epoch() const; + +inline Duration operator*(const int& lhs, const Duration& rhs) +{ + return rhs * lhs; +} + +#endif // ENABLE_STDCXX_SYNC + +// NOTE: Moved the following class definitions to "atomic_clock.h" +// template +// class AtomicDuration; +// template +// class AtomicClock; + +/////////////////////////////////////////////////////////////////////////////// +// +// Duration and timepoint conversions +// +/////////////////////////////////////////////////////////////////////////////// + +/// Function return number of decimals in a subsecond precision. +/// E.g. for a microsecond accuracy of steady_clock the return would be 6. +/// For a nanosecond accuracy of the steady_clock the return value would be 9. +int clockSubsecondPrecision(); + +#if ENABLE_STDCXX_SYNC + +inline long long count_microseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_microseconds(const steady_clock::time_point tp) +{ + return std::chrono::duration_cast(tp.time_since_epoch()).count(); +} + +inline long long count_milliseconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline long long count_seconds(const steady_clock::duration &t) +{ + return std::chrono::duration_cast(t).count(); +} + +inline steady_clock::duration microseconds_from(int64_t t_us) +{ + return std::chrono::microseconds(t_us); +} + +inline steady_clock::duration milliseconds_from(int64_t t_ms) +{ + return std::chrono::milliseconds(t_ms); +} + +inline steady_clock::duration seconds_from(int64_t t_s) +{ + return std::chrono::seconds(t_s); +} + +#else + +int64_t count_microseconds(const steady_clock::duration& t); +int64_t count_milliseconds(const steady_clock::duration& t); +int64_t count_seconds(const steady_clock::duration& t); + +Duration microseconds_from(int64_t t_us); +Duration milliseconds_from(int64_t t_ms); +Duration seconds_from(int64_t t_s); + +inline bool is_zero(const TimePoint& t) +{ + return t == TimePoint(); +} + +#endif // ENABLE_STDCXX_SYNC + + +/////////////////////////////////////////////////////////////////////////////// +// +// Mutex section +// +/////////////////////////////////////////////////////////////////////////////// + +#if ENABLE_STDCXX_SYNC +using Mutex = std::mutex; +using UniqueLock = std::unique_lock; +using ScopedLock = std::lock_guard; +#else +/// Mutex is a class wrapper, that should mimic the std::chrono::mutex class. +/// At the moment the extra function ref() is temporally added to allow calls +/// to pthread_cond_timedwait(). Will be removed by introducing CEvent. +class SRT_ATTR_CAPABILITY("mutex") Mutex +{ + friend class SyncEvent; + +public: + Mutex(); + ~Mutex(); + +public: + int lock() SRT_ATTR_ACQUIRE(); + int unlock() SRT_ATTR_RELEASE(); + + /// @return true if the lock was acquired successfully, otherwise false + bool try_lock() SRT_ATTR_TRY_ACQUIRE(true); + + // TODO: To be removed with introduction of the CEvent. + pthread_mutex_t& ref() { return m_mutex; } + +private: + pthread_mutex_t m_mutex; +}; + +/// A pthread version of std::chrono::scoped_lock (or lock_guard for C++11) +class SRT_ATTR_SCOPED_CAPABILITY ScopedLock +{ +public: + SRT_ATTR_ACQUIRE(m) + explicit ScopedLock(Mutex& m); + + SRT_ATTR_RELEASE() + ~ScopedLock(); + +private: + Mutex& m_mutex; +}; + +/// A pthread version of std::chrono::unique_lock +class SRT_ATTR_SCOPED_CAPABILITY UniqueLock +{ + friend class SyncEvent; + int m_iLocked; + Mutex& m_Mutex; + +public: + SRT_ATTR_ACQUIRE(m) + explicit UniqueLock(Mutex &m); + + SRT_ATTR_RELEASE() + ~UniqueLock(); + +public: + SRT_ATTR_ACQUIRE() + void lock(); + + SRT_ATTR_RELEASE() + void unlock(); + + SRT_ATTR_RETURN_CAPABILITY(m_Mutex) + Mutex* mutex(); // reflects C++11 unique_lock::mutex() +}; +#endif // ENABLE_STDCXX_SYNC + +inline void enterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) { m.lock(); } + +inline bool tryEnterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_TRY_ACQUIRE(true, m) { return m.try_lock(); } + +inline void leaveCS(Mutex& m) SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) { m.unlock(); } + +class InvertedLock +{ + Mutex& m_mtx; + +public: + SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) + InvertedLock(Mutex& m) + : m_mtx(m) + { + m_mtx.unlock(); + } + + SRT_ATTR_ACQUIRE(m_mtx) + ~InvertedLock() + { + m_mtx.lock(); + } +}; + +inline void setupMutex(Mutex&, const char*) {} +inline void releaseMutex(Mutex&) {} + +//////////////////////////////////////////////////////////////////////////////// +// +// Condition section +// +//////////////////////////////////////////////////////////////////////////////// + +class Condition +{ +public: + Condition(); + ~Condition(); + +public: + /// These functions do not align with C++11 version. They are here hopefully as a temporal solution + /// to avoud issues with static initialization of CV on windows. + void init(); + void destroy(); + +public: + /// Causes the current thread to block until the condition variable is notified + /// or a spurious wakeup occurs. + /// + /// @param lock Corresponding mutex locked by UniqueLock + void wait(UniqueLock& lock); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on *this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. When unblocked, regardless of the reason, + /// lock is reacquired and wait_for() exits. + /// + /// @returns false if the relative timeout specified by rel_time expired, + /// true otherwise (signal or spurious wake up). + /// + /// @note Calling this function if lock.mutex() + /// is not locked by the current thread is undefined behavior. + /// Calling this function if lock.mutex() is not the same mutex as the one + /// used by all other threads that are currently waiting on the same + /// condition variable is undefined behavior. + bool wait_for(UniqueLock& lock, const steady_clock::duration& rel_time); + + /// Causes the current thread to block until the condition variable is notified, + /// a specific time is reached, or a spurious wakeup occurs. + /// + /// @param[in] lock an object of type UniqueLock, which must be locked by the current thread + /// @param[in] timeout_time an object of type time_point representing the time when to stop waiting + /// + /// @returns false if the relative timeout specified by timeout_time expired, + /// true otherwise (signal or spurious wake up). + bool wait_until(UniqueLock& lock, const steady_clock::time_point& timeout_time); + + /// Calling notify_one() unblocks one of the waiting threads, + /// if any threads are waiting on this CV. + void notify_one(); + + /// Unblocks all threads currently waiting for this CV. + void notify_all(); + +private: +#if ENABLE_STDCXX_SYNC + std::condition_variable m_cv; +#else + pthread_cond_t m_cv; +#endif +}; + +inline void setupCond(Condition& cv, const char*) { cv.init(); } +inline void releaseCond(Condition& cv) { cv.destroy(); } + +/////////////////////////////////////////////////////////////////////////////// +// +// Event (CV) section +// +/////////////////////////////////////////////////////////////////////////////// + +// This class is used for condition variable combined with mutex by different ways. +// This should provide a cleaner API around locking with debug-logging inside. +class CSync +{ +protected: + Condition* m_cond; + UniqueLock* m_locker; + +public: + // Locked version: must be declared only after the declaration of UniqueLock, + // which has locked the mutex. On this delegate you should call only + // signal_locked() and pass the UniqueLock variable that should remain locked. + // Also wait() and wait_for() can be used only with this socket. + CSync(Condition& cond, UniqueLock& g) + : m_cond(&cond), m_locker(&g) + { + // XXX it would be nice to check whether the owner is also current thread + // but this can't be done portable way. + + // When constructed by this constructor, the user is expected + // to only call signal_locked() function. You should pass the same guard + // variable that you have used for construction as its argument. + } + + // COPY CONSTRUCTOR: DEFAULT! + + // Wait indefinitely, until getting a signal on CV. + void wait() + { + m_cond->wait(*m_locker); + } + + /// Block the call until either @a timestamp time achieved + /// or the conditional is signaled. + /// @param [in] delay Maximum time to wait since the moment of the call + /// @retval false if the relative timeout specified by rel_time expired, + /// @retval true if condition is signaled or spurious wake up. + bool wait_for(const steady_clock::duration& delay) + { + return m_cond->wait_for(*m_locker, delay); + } + + // Wait until the given time is achieved. + /// @param [in] exptime The target time to wait until. + /// @retval false if the target wait time is reached. + /// @retval true if condition is signal or spurious wake up. + bool wait_until(const steady_clock::time_point& exptime) + { + return m_cond->wait_until(*m_locker, exptime); + } + + // Static ad-hoc version + static void lock_notify_one(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_one(); + } + + static void lock_notify_all(Condition& cond, Mutex& m) + { + ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! + cond.notify_all(); + } + + void notify_one_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_one(); + } + + void notify_all_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_all(); + } + + // The *_relaxed functions are to be used in case when you don't care + // whether the associated mutex is locked or not (you accept the case that + // a mutex isn't locked and the condition notification gets effectively + // missed), or you somehow know that the mutex is locked, but you don't + // have access to the associated UniqueLock object. This function, although + // it does the same thing as CSync::notify_one_locked etc. here for the + // user to declare explicitly that notifying is done without being + // prematurely certain that the associated mutex is locked. + // + // It is then expected that whenever these functions are used, an extra + // comment is provided to explain, why the use of the relaxed notification + // is correctly used. + + void notify_one_relaxed() { notify_one_relaxed(*m_cond); } + static void notify_one_relaxed(Condition& cond) { cond.notify_one(); } + static void notify_all_relaxed(Condition& cond) { cond.notify_all(); } +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +// XXX Do not use this class now, there's an unknown issue +// connected to object management with the use of release* functions. +// Until this is solved, stay with separate *Cond and *Lock fields. +class CEvent +{ +public: + CEvent(); + ~CEvent(); + +public: + Mutex& mutex() { return m_lock; } + Condition& cond() { return m_cond; } + +public: + /// Causes the current thread to block until + /// a specific time is reached. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_until(const steady_clock::time_point& tp); + + /// Blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// Uses internal mutex to lock. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool lock_wait_for(const steady_clock::duration& rel_time); + + /// Atomically releases lock, blocks the current executing thread, + /// and adds it to the list of threads waiting on* this. + /// The thread will be unblocked when notify_all() or notify_one() is executed, + /// or when the relative timeout rel_time expires. + /// It may also be unblocked spuriously. + /// When unblocked, regardless of the reason, lock is reacquiredand wait_for() exits. + /// + /// @return true if condition occurred or spuriously woken up + /// false on timeout + bool wait_for(UniqueLock& lk, const steady_clock::duration& rel_time); + + void lock_wait(); + + void wait(UniqueLock& lk); + + void notify_one(); + + void notify_all(); + + void lock_notify_one() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_one(); + } + + void lock_notify_all() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_all(); + } + +private: + Mutex m_lock; + Condition m_cond; +}; + + +// This class binds together the functionality of +// UniqueLock and CSync. It provides a simple interface of CSync +// while having already the UniqueLock applied in the scope, +// so a safe statement can be made about the mutex being locked +// when signalling or waiting. +class CUniqueSync: public CSync +{ + UniqueLock m_ulock; + +public: + + UniqueLock& locker() { return m_ulock; } + + CUniqueSync(Mutex& mut, Condition& cnd) + : CSync(cnd, m_ulock) + , m_ulock(mut) + { + } + + CUniqueSync(CEvent& event) + : CSync(event.cond(), m_ulock) + , m_ulock(event.mutex()) + { + } + + // These functions can be used safely because + // this whole class guarantees that whatever happens + // while its object exists is that the mutex is locked. + + void notify_one() + { + m_cond->notify_one(); + } + + void notify_all() + { + m_cond->notify_all(); + } +}; + +class CTimer +{ +public: + CTimer(); + ~CTimer(); + +public: + /// Causes the current thread to block until + /// the specified time is reached. + /// Sleep can be interrupted by calling interrupt() + /// or woken up to recheck the scheduled time by tick() + /// @param tp target time to sleep until + /// + /// @return true if the specified time was reached + /// false should never happen + bool sleep_until(steady_clock::time_point tp); + + /// Resets target wait time and interrupts waiting + /// in sleep_until(..) + void interrupt(); + + /// Wakes up waiting thread (sleep_until(..)) without + /// changing the target waiting time to force a recheck + /// of the current time in comparisson to the target time. + void tick(); + +private: + CEvent m_event; + steady_clock::time_point m_tsSchedTime; +}; + + +/// Print steady clock timepoint in a human readable way. +/// days HH:MM:SS.us [STD] +/// Example: 1D 02:12:56.123456 +/// +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTime(const steady_clock::time_point& time); + +/// Print steady clock timepoint relative to the current system time +/// Date HH:MM:SS.us [SYS] +/// @param [in] steady clock timepoint +/// @returns a string with a formatted time representation +std::string FormatTimeSys(const steady_clock::time_point& time); + +enum eDurationUnit {DUNIT_S, DUNIT_MS, DUNIT_US}; + +template +struct DurationUnitName; + +template<> +struct DurationUnitName +{ + static const char* name() { return "us"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur)); } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "ms"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000.0; } +}; + +template<> +struct DurationUnitName +{ + static const char* name() { return "s"; } + static double count(const steady_clock::duration& dur) { return static_cast(count_microseconds(dur))/1000000.0; } +}; + +template +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return Sprint(DurationUnitName::count(dur)) + DurationUnitName::name(); +} + +inline std::string FormatDuration(const steady_clock::duration& dur) +{ + return FormatDuration(dur); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// CGlobEvent class +// +//////////////////////////////////////////////////////////////////////////////// + +class CGlobEvent +{ +public: + /// Triggers the event and notifies waiting threads. + /// Simply calls notify_one(). + static void triggerEvent(); + + /// Waits for the event to be triggered with 10ms timeout. + /// Simply calls wait_for(). + static bool waitForEvent(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// CThread class +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef ENABLE_STDCXX_SYNC +typedef std::system_error CThreadException; +using CThread = std::thread; +namespace this_thread = std::this_thread; +#else // pthreads wrapper version +typedef CUDTException CThreadException; + +class CThread +{ +public: + CThread(); + /// @throws std::system_error if the thread could not be started. + CThread(void *(*start_routine) (void *), void *arg); + +#if HAVE_FULL_CXX11 + CThread& operator=(CThread &other) = delete; + CThread& operator=(CThread &&other); +#else + CThread& operator=(CThread &other); + /// To be used only in StartThread function. + /// Creates a new stread and assigns to this. + /// @throw CThreadException + void create_thread(void *(*start_routine) (void *), void *arg); +#endif + +public: // Observers + /// Checks if the CThread object identifies an active thread of execution. + /// A default constructed thread is not joinable. + /// A thread that has finished executing code, but has not yet been joined + /// is still considered an active thread of execution and is therefore joinable. + bool joinable() const; + + struct id + { + explicit id(const pthread_t t) + : value(t) + {} + + const pthread_t value; + inline bool operator==(const id& second) const + { + return pthread_equal(value, second.value) != 0; + } + }; + + /// Returns the id of the current thread. + /// In this implementation the ID is the pthread_t. + const id get_id() const { return id(m_thread); } + +public: + /// Blocks the current thread until the thread identified by *this finishes its execution. + /// If that thread has already terminated, then join() returns immediately. + /// + /// @throws std::system_error if an error occurs + void join(); + +public: // Internal + /// Calls pthread_create, throws exception on failure. + /// @throw CThreadException + void create(void *(*start_routine) (void *), void *arg); + +private: + pthread_t m_thread; +}; + +template +inline Stream& operator<<(Stream& str, const CThread::id& cid) +{ +#if defined(_WIN32) && (defined(PTW32_VERSION) || defined (__PTW32_VERSION)) + // This is a version specific for pthread-win32 implementation + // Here pthread_t type is a structure that is not convertible + // to a number at all. + return str << pthread_getw32threadid_np(cid.value); +#else + return str << cid.value; +#endif +} + +namespace this_thread +{ + const inline CThread::id get_id() { return CThread::id (pthread_self()); } + + inline void sleep_for(const steady_clock::duration& t) + { +#if !defined(_WIN32) + usleep(count_microseconds(t)); // microseconds +#else + Sleep((DWORD) count_milliseconds(t)); +#endif + } +} + +#endif + +/// StartThread function should be used to do CThread assignments: +/// @code +/// CThread a(); +/// a = CThread(func, args); +/// @endcode +/// +/// @returns true if thread was started successfully, +/// false on failure +/// +#ifdef ENABLE_STDCXX_SYNC +typedef void* (&ThreadFunc) (void*); +bool StartThread(CThread& th, ThreadFunc&& f, void* args, const std::string& name); +#else +bool StartThread(CThread& th, void* (*f) (void*), void* args, const std::string& name); +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// CThreadError class - thread local storage wrapper +// +//////////////////////////////////////////////////////////////////////////////// + +/// Set thread local error +/// @param e new CUDTException +void SetThreadLocalError(const CUDTException& e); + +/// Get thread local error +/// @returns CUDTException pointer +CUDTException& GetThreadLocalError(); + +//////////////////////////////////////////////////////////////////////////////// +// +// Random distribution functions. +// +//////////////////////////////////////////////////////////////////////////////// + +/// Generate a uniform-distributed random integer from [minVal; maxVal]. +/// If HAVE_CXX11, uses std::uniform_distribution(std::random_device). +/// @param[in] minVal minimum allowed value of the resulting random number. +/// @param[in] maxVal maximum allowed value of the resulting random number. +int genRandomInt(int minVal, int maxVal); + +} // namespace sync +} // namespace srt + +#include "atomic_clock.h" + +#endif // INC_SRT_SYNC_H diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/threadname.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/threadname.h new file mode 100644 index 000000000..1c064c86c --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/threadname.h @@ -0,0 +1,224 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_THREADNAME_H +#define INC_SRT_THREADNAME_H + +// NOTE: +// HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_GETNAME_NP +// HAVE_PTHREAD_GETNAME_NP +// Are detected and set in ../CMakeLists.txt. +// OS Availability of pthread_getname_np(..) and pthread_setname_np(..):: +// MacOS(10.6) +// iOS(3.2) +// AIX(7.1) +// FreeBSD(version?), OpenBSD(Version?) +// Linux-GLIBC(GLIBC-2.12). +// Linux-MUSL(MUSL-1.1.20 Partial Implementation. See below). +// MINGW-W64(4.0.6) + +#if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + || defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + #include + #if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_GETNAME_NP) + #define HAVE_PTHREAD_GETNAME_NP 1 + #endif + #if defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_SETNAME_NP) + #define HAVE_PTHREAD_SETNAME_NP 1 + #endif +#endif + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + // NOTE: + // Linux pthread_getname_np() and pthread_setname_np() became available + // in GLIBC-2.12 and later. + // Some Linux runtimes do not have pthread_getname_np(), but have + // pthread_setname_np(), for instance MUSL at least as of v1.1.20. + // So using the prctl() for Linux is more portable. + #if defined(__linux__) + #include + #endif + #include +#endif + +#include +#include +#include + +#include "common.h" +#include "sync.h" + +namespace srt { + +class ThreadName +{ + +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + + class ThreadNameImpl + { + public: + static const size_t BUFSIZE = 64; + static const bool DUMMY_IMPL = false; + + static bool get(char* namebuf) + { +#if defined(__linux__) + // since Linux 2.6.11. The buffer should allow space for up to 16 + // bytes; the returned string will be null-terminated. + return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_GETNAME_NP) + return pthread_getname_np(pthread_self(), namebuf, BUFSIZE) == 0; +#else +#error "unsupported platform" +#endif + } + + static bool set(const char* name) + { + SRT_ASSERT(name != NULL); +#if defined(__linux__) + // The name can be up to 16 bytes long, including the terminating + // null byte. (If the length of the string, including the terminating + // null byte, exceeds 16 bytes, the string is silently truncated.) + return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; +#elif defined(HAVE_PTHREAD_SETNAME_NP) + #if defined(__APPLE__) + return pthread_setname_np(name) == 0; + #else + return pthread_setname_np(pthread_self(), name) == 0; + #endif +#else +#error "unsupported platform" +#endif + } + + explicit ThreadNameImpl(const std::string& name) + : reset(false) + { + tid = pthread_self(); + + if (!get(old_name)) + return; + + reset = set(name.c_str()); + if (reset) + return; + + // Try with a shorter name. 15 is the upper limit supported by Linux, + // other platforms should support a larger value. So 15 should works + // on all platforms. + const size_t max_len = 15; + if (name.size() > max_len) + reset = set(name.substr(0, max_len).c_str()); + } + + ~ThreadNameImpl() + { + if (!reset) + return; + + // ensure it's called on the right thread + if (tid == pthread_self()) + set(old_name); + } + + private: + ThreadNameImpl(ThreadNameImpl& other); + ThreadNameImpl& operator=(const ThreadNameImpl& other); + + private: + bool reset; + pthread_t tid; + char old_name[BUFSIZE]; + }; + +#else + + class ThreadNameImpl + { + public: + static const bool DUMMY_IMPL = true; + static const size_t BUFSIZE = 64; + + static bool get(char* output) + { + // The default implementation will simply try to get the thread ID + std::ostringstream bs; + bs << "T" << sync::this_thread::get_id(); + size_t s = bs.str().copy(output, BUFSIZE - 1); + output[s] = '\0'; + return true; + } + + static bool set(const char*) { return false; } + + ThreadNameImpl(const std::string&) {} + + ~ThreadNameImpl() // just to make it "non-trivially-destructible" for compatibility with normal version + { + } + }; + +#endif // platform dependent impl + + // Why delegate to impl: + // 1. to make sure implementation on different platforms have the same interface. + // 2. it's simple to add some wrappers like get(const std::string &). + ThreadNameImpl impl; + +public: + static const bool DUMMY_IMPL = ThreadNameImpl::DUMMY_IMPL; + static const size_t BUFSIZE = ThreadNameImpl::BUFSIZE; + + /// @brief Print thread ID to the provided buffer. + /// The size of the destination buffer is assumed to be at least ThreadName::BUFSIZE. + /// @param [out] output destination buffer to get thread name + /// @return true on success, false on failure + static bool get(char* output) { + return ThreadNameImpl::get(output); + } + + static bool get(std::string& name) + { + char buf[BUFSIZE]; + bool ret = get(buf); + if (ret) + name = buf; + return ret; + } + + static bool set(const std::string& name) { return ThreadNameImpl::set(name.c_str()); } + + explicit ThreadName(const std::string& name) + : impl(name) + { + } + +private: + ThreadName(const ThreadName&); + ThreadName(const char*); + ThreadName& operator=(const ThreadName& other); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/tsbpd_time.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/tsbpd_time.h new file mode 100644 index 000000000..3483c197f --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/tsbpd_time.h @@ -0,0 +1,163 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2021 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INC_SRT_TSBPD_TIME_H +#define INC_SRT_TSBPD_TIME_H + +#include "platform_sys.h" +#include "sync.h" +#include "utilities.h" + +namespace srt +{ + +/// @brief TimeStamp-Based Packet Delivery Mode (TSBPD) time conversion logic. +/// Used by the receiver to calculate delivery time of data packets. +/// See SRT Internet Draft Section "Timestamp-Based Packet Delivery". +class CTsbpdTime +{ + typedef srt::sync::steady_clock steady_clock; + typedef steady_clock::time_point time_point; + typedef steady_clock::duration duration; + typedef srt::sync::Mutex Mutex; + +public: + CTsbpdTime() + : m_iFirstRTT(-1) + , m_bTsbPdMode(false) + , m_tdTsbPdDelay(0) + , m_bTsbPdWrapCheck(false) + { + } + + /// Set TimeStamp-Based Packet Delivery Mode (receiver). + /// @param [in] timebase local time base (uSec) of packet time stamps including buffering delay. + /// @param [in] wrap wrapping period. + /// @param [in] delay negotiated TsbPD delay (buffering latency). + void setTsbPdMode(const time_point& timebase, bool wrap, duration delay); + + /// @brief Check if TSBPD logic is enabled. + /// @return true if TSBPD is enabled. + bool isEnabled() const { return m_bTsbPdMode; } + + /// @brief Apply new state derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp wrap period (enabled or not). + /// @param delay TSBPD delay. + /// @param udrift clock drift. + void applyGroupTime(const time_point& timebase, bool wrp, uint32_t delay, const duration& udrift); + + /// @brief Apply new clock state (TSBPD base and drift) derived from other members of a socket group. + /// @param timebase TSBPD base time. + /// @param wrp state of the wrapping period (enabled or disabled). + /// @param udrift clock drift. + void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift); + + /// @brief Add new drift sample from an ACK-ACKACK pair. + /// ACKACK packets are sent immediately (except for UDP buffering). + /// Therefore their timestamp roughly corresponds to the time of sending + /// and can be used to estimate clock drift. + /// + /// @param [in] pktTimestamp Timestamp of the arrived ACKACK packet. + /// @param [in] tsPktArrival packet arrival time. + /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. If no sample, pass '-1'. + /// + /// @return true if TSBPD base time has changed, false otherwise. + bool addDriftSample(uint32_t pktTimestamp, const time_point& tsPktArrival, int usRTTSample); + + /// @brief Handle timestamp of data packet when 32-bit integer carryover is about to happen. + /// When packet timestamp approaches CPacket::MAX_TIMESTAMP, the TSBPD base time should be + /// shifted accordingly to correctly handle new packets with timestamps starting from zero. + /// @param usPktTimestamp timestamp field value of a data packet. + void updateTsbPdTimeBase(uint32_t usPktTimestamp); + + /// @brief Get TSBPD base time adjusted for carryover, which occurs when + /// a packet's timestamp exceeds the UINT32_MAX and continues from zero. + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return TSBPD base time for a provided packet timestamp. + time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time without buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application. + /// Essentially: getTsbPdTimeBase(usPktTimestamp) + usPktTimestamp + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD base time without buffering delay. + time_point getPktTsbPdBaseTime(uint32_t usPktTimestamp) const; + + /// @brief Get packet TSBPD time with buffering delay and clock drift, which is + /// the target time for delivering the packet to an upstream application + /// (including drift and carryover effects, if any). + /// Essentially: getPktTsbPdBaseTime(usPktTimestamp) + m_tdTsbPdDelay + drift() + /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds). + /// + /// @return Packet TSBPD time with buffering delay. + time_point getPktTsbPdTime(uint32_t usPktTimestamp) const; + + /// @brief Get current drift value. + /// @return current drift value. + int64_t drift() const { return m_DriftTracer.drift(); } + + /// @brief Get current overdrift value. + /// @return current overdrift value. + int64_t overdrift() const { return m_DriftTracer.overdrift(); } + + /// @brief Get internal state to apply to another member of a socket group. + /// @param w_tb TsbPd base time. + /// @param w_udrift drift value. + /// @param w_wrp wrap check. + void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift) const; + +private: + int m_iFirstRTT; // First measured RTT sample. + bool m_bTsbPdMode; // Receiver buffering and TSBPD is active when true. + duration m_tdTsbPdDelay; // Negotiated buffering delay. + + /// @brief Local time base for TsbPd. + /// @note m_tsTsbPdTimeBase is changed in the following cases: + /// 1. Initialized upon SRT_CMD_HSREQ packet as the difference with the current time: + /// = (NOW - PACKET_TIMESTAMP), at the time of HSREQ reception. + /// 2. Shifted forward on timestamp overflow (@see CTsbpdTime::updateTsbPdTimeBase), when overflow + /// of the timestamp field value of a data packet is detected. + /// += CPacket::MAX_TIMESTAMP + 1 + /// 3. Clock drift (@see CTsbpdTime::addDriftSample, executed exclusively + /// from ACKACK handler). This is updated with (positive or negative) TSBPD_DRIFT_MAX_VALUE + /// once the value of average drift exceeds this value in either direction. + /// += (+/-)TSBPD_DRIFT_MAX_VALUE + /// + /// @note The TSBPD base time is expected to hold the following condition: + /// (PACKET_TIMESTAMP + m_tsTsbPdTimeBase + drift) == NOW. + /// Then it can be used to estimate the origin time of a data packet, and calculate its delivery time + /// with buffering delay applied. + time_point m_tsTsbPdTimeBase; + + /// @note Packet timestamps wrap around every 01h11m35s (32-bit in usec). + /// A wrap check period starts 30 seconds (TSBPD_WRAP_PERIOD) before the wrap point. + /// During the wrap check period, packet timestamps smaller than 30 seconds + /// are considered to have been wrapped around. + /// The wrap check period ends 30 seconds after the wrap point, + /// after which the TSBPD base time is adjusted. + bool m_bTsbPdWrapCheck; // true: check packet time stamp wraparound (overflow). + static const uint32_t TSBPD_WRAP_PERIOD = (30 * 1000000); // 30 seconds (in usec) for timestamp wrapping period. + + /// Maximum clock drift (microseconds) above which TsbPD base time is already adjusted. + static const int TSBPD_DRIFT_MAX_VALUE = 5000; + /// Number of samples (ACKACK packets) on which to perform drift calculation and compensation. + static const int TSBPD_DRIFT_MAX_SAMPLES = 1000; + DriftTracer m_DriftTracer; + + /// Protect simultaneous change of state (read/write). + mutable Mutex m_mtxRW; +}; + +} // namespace srt + +#endif // INC_SRT_TSBPD_TIME_H diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/udt.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/udt.h index 77f903bd5..ee4c02f4d 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/udt.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/udt.h @@ -64,16 +64,16 @@ modified by * file doesn't contain _FUNCTIONS_ predicted to be used in C - see udtc.h */ -#ifndef __UDT_H__ -#define __UDT_H__ +#ifndef INC_SRT_UDT_H +#define INC_SRT_UDT_H #include "srt.h" /* -* SRT_ENABLE_THREADCHECK (THIS IS SET IN MAKEFILE NOT HERE) +* SRT_ENABLE_THREADCHECK IS SET IN MAKEFILE, NOT HERE */ #if defined(SRT_ENABLE_THREADCHECK) -#include +#include "threadcheck.h" #else #define THREAD_STATE_INIT(name) #define THREAD_EXIT() @@ -82,13 +82,6 @@ modified by #define INCREMENT_THREAD_ITERATIONS() #endif -/* Obsolete way to define MINGW */ -#ifndef __MINGW__ -#if defined(__MINGW32__) || defined(__MINGW64__) -#define __MINGW__ 1 -#endif -#endif - #ifdef __cplusplus #include #include @@ -96,10 +89,6 @@ modified by #include #endif - -// Legacy/backward/deprecated -#define UDT_API SRT_API - //////////////////////////////////////////////////////////////////////////////// //if compiling on VC6.0 or pre-WindowsXP systems @@ -108,83 +97,6 @@ modified by //if compiling with MinGW, it only works on XP or above //use -D_WIN32_WINNT=0x0501 - -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -// This facility is used only for select() function. -// This is considered obsolete and the epoll() functionality rather should be used. -typedef std::set ud_set; -#define UD_CLR(u, uset) ((uset)->erase(u)) -#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) -#define UD_SET(u, uset) ((uset)->insert(u)) -#define UD_ZERO(uset) ((uset)->clear()) -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Legacy names - -#define UDT_MSS SRTO_MSS -#define UDT_SNDSYN SRTO_SNDSYN -#define UDT_RCVSYN SRTO_RCVSYN -#define UDT_FC SRTO_FC -#define UDT_SNDBUF SRTO_SNDBUF -#define UDT_RCVBUF SRTO_RCVBUF -#define UDT_LINGER SRTO_LINGER -#define UDP_SNDBUF SRTO_UDP_SNDBUF -#define UDP_RCVBUF SRTO_UDP_RCVBUF -#define UDT_MAXMSG SRTO_MAXMSG -#define UDT_MSGTTL SRTO_MSGTTL -#define UDT_RENDEZVOUS SRTO_RENDEZVOUS -#define UDT_SNDTIMEO SRTO_SNDTIMEO -#define UDT_RCVTIMEO SRTO_RCVTIMEO -#define UDT_REUSEADDR SRTO_REUSEADDR -#define UDT_MAXBW SRTO_MAXBW -#define UDT_STATE SRTO_STATE -#define UDT_EVENT SRTO_EVENT -#define UDT_SNDDATA SRTO_SNDDATA -#define UDT_RCVDATA SRTO_RCVDATA -#define SRT_SENDER SRTO_SENDER -#define SRT_TSBPDMODE SRTO_TSBPDMODE -#define SRT_TSBPDDELAY SRTO_TSBPDDELAY -#define SRT_INPUTBW SRTO_INPUTBW -#define SRT_OHEADBW SRTO_OHEADBW -#define SRT_PASSPHRASE SRTO_PASSPHRASE -#define SRT_PBKEYLEN SRTO_PBKEYLEN -#define SRT_KMSTATE SRTO_KMSTATE -#define SRT_IPTTL SRTO_IPTTL -#define SRT_IPTOS SRTO_IPTOS -#define SRT_TLPKTDROP SRTO_TLPKTDROP -#define SRT_TSBPDMAXLAG SRTO_TSBPDMAXLAG -#define SRT_RCVNAKREPORT SRTO_NAKREPORT -#define SRT_CONNTIMEO SRTO_CONNTIMEO -#define SRT_SNDPBKEYLEN SRTO_SNDPBKEYLEN -#define SRT_RCVPBKEYLEN SRTO_RCVPBKEYLEN -#define SRT_SNDPEERKMSTATE SRTO_SNDPEERKMSTATE -#define SRT_RCVKMSTATE SRTO_RCVKMSTATE - -#define UDT_EPOLL_OPT SRT_EPOLL_OPT -#define UDT_EPOLL_IN SRT_EPOLL_IN -#define UDT_EPOLL_OUT SRT_EPOLL_OUT -#define UDT_EPOLL_ERR SRT_EPOLL_ERR - -/* Binary backward compatibility obsolete options */ -#define SRT_NAKREPORT SRT_RCVNAKREPORT - -#if !defined(SRT_DISABLE_LEGACY_UDTSTATUS) -#define UDTSTATUS SRT_SOCKSTATUS -#define INIT SRTS_INIT -#define OPENED SRTS_OPENED -#define LISTENING SRTS_LISTENING -#define CONNECTING SRTS_CONNECTING -#define CONNECTED SRTS_CONNECTED -#define BROKEN SRTS_BROKEN -#define CLOSING SRTS_CLOSING -#define CLOSED SRTS_CLOSED -#define NONEXIST SRTS_NONEXIST -#endif - //////////////////////////////////////////////////////////////////////////////// struct CPerfMon @@ -236,166 +148,75 @@ typedef SRTSOCKET UDTSOCKET; //legacy alias #ifdef __cplusplus -// Class CUDTException exposed for C++ API. -// This is actually useless, unless you'd use a DIRECT C++ API, -// however there's no such API so far. The current C++ API for UDT/SRT -// is predicted to NEVER LET ANY EXCEPTION out of implementation, -// so it's useless to catch this exception anyway. - -class UDT_API CUDTException -{ -public: - - CUDTException(CodeMajor major = MJ_SUCCESS, CodeMinor minor = MN_NONE, int err = -1); - CUDTException(const CUDTException& e); - - ~CUDTException(); - - /// Get the description of the exception. - /// @return Text message for the exception description. - - const char* getErrorMessage(); - - /// Get the system errno for the exception. - /// @return errno. - - int getErrorCode() const; - - /// Get the system network errno for the exception. - /// @return errno. - - int getErrno() const; - /// Clear the error code. - - void clear(); - -private: - CodeMajor m_iMajor; // major exception categories - CodeMinor m_iMinor; // for specific error reasons - int m_iErrno; // errno returned by the system if there is any - std::string m_strMsg; // text error message - - std::string m_strAPI; // the name of UDT function that returns the error - std::string m_strDebug; // debug information, set to the original place that causes the error - -public: // Legacy Error Code - - static const int EUNKNOWN = SRT_EUNKNOWN; - static const int SUCCESS = SRT_SUCCESS; - static const int ECONNSETUP = SRT_ECONNSETUP; - static const int ENOSERVER = SRT_ENOSERVER; - static const int ECONNREJ = SRT_ECONNREJ; - static const int ESOCKFAIL = SRT_ESOCKFAIL; - static const int ESECFAIL = SRT_ESECFAIL; - static const int ECONNFAIL = SRT_ECONNFAIL; - static const int ECONNLOST = SRT_ECONNLOST; - static const int ENOCONN = SRT_ENOCONN; - static const int ERESOURCE = SRT_ERESOURCE; - static const int ETHREAD = SRT_ETHREAD; - static const int ENOBUF = SRT_ENOBUF; - static const int EFILE = SRT_EFILE; - static const int EINVRDOFF = SRT_EINVRDOFF; - static const int ERDPERM = SRT_ERDPERM; - static const int EINVWROFF = SRT_EINVWROFF; - static const int EWRPERM = SRT_EWRPERM; - static const int EINVOP = SRT_EINVOP; - static const int EBOUNDSOCK = SRT_EBOUNDSOCK; - static const int ECONNSOCK = SRT_ECONNSOCK; - static const int EINVPARAM = SRT_EINVPARAM; - static const int EINVSOCK = SRT_EINVSOCK; - static const int EUNBOUNDSOCK = SRT_EUNBOUNDSOCK; - static const int ESTREAMILL = SRT_EINVALMSGAPI; - static const int EDGRAMILL = SRT_EINVALBUFFERAPI; - static const int ENOLISTEN = SRT_ENOLISTEN; - static const int ERDVNOSERV = SRT_ERDVNOSERV; - static const int ERDVUNBOUND = SRT_ERDVUNBOUND; - static const int EINVALMSGAPI = SRT_EINVALMSGAPI; - static const int EINVALBUFFERAPI = SRT_EINVALBUFFERAPI; - static const int EDUPLISTEN = SRT_EDUPLISTEN; - static const int ELARGEMSG = SRT_ELARGEMSG; - static const int EINVPOLLID = SRT_EINVPOLLID; - static const int EASYNCFAIL = SRT_EASYNCFAIL; - static const int EASYNCSND = SRT_EASYNCSND; - static const int EASYNCRCV = SRT_EASYNCRCV; - static const int ETIMEOUT = SRT_ETIMEOUT; - static const int ECONGEST = SRT_ECONGEST; - static const int EPEERERR = SRT_EPEERERR; -}; +namespace srt { class CUDTException; } namespace UDT { -typedef CUDTException ERRORINFO; -//typedef UDT_SOCKOPT SOCKOPT; +typedef srt::CUDTException ERRORINFO; typedef CPerfMon TRACEINFO; -typedef CBytePerfMon TRACEBSTATS; -typedef ud_set UDSET; -UDT_API extern const SRTSOCKET INVALID_SOCK; +// This facility is used only for select() function. +// This is considered obsolete and the epoll() functionality rather should be used. +typedef std::set UDSET; +#define UD_CLR(u, uset) ((uset)->erase(u)) +#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) +#define UD_SET(u, uset) ((uset)->insert(u)) +#define UD_ZERO(uset) ((uset)->clear()) + +SRT_API extern const SRTSOCKET INVALID_SOCK; #undef ERROR -UDT_API extern const int ERROR; - -UDT_API int startup(); -UDT_API int cleanup(); -UDT_API UDTSOCKET socket(int af, int type, int protocol); -UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock); -UDT_API int listen(UDTSOCKET u, int backlog); -UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen); -UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int close(UDTSOCKET u); -UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); -UDT_API int setsockopt(UDTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); -UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags); -UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags); - -UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, uint64_t srctime = 0); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len, uint64_t& srctime); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len); - -UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); -UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); +SRT_API extern const int ERROR; + +SRT_API int startup(); +SRT_API int cleanup(); +SRT_API SRTSOCKET socket(); +inline SRTSOCKET socket(int , int , int ) { return socket(); } +SRT_API int bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int bind2(SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int listen(SRTSOCKET u, int backlog); +SRT_API SRTSOCKET accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API int connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int close(SRTSOCKET u); +SRT_API int getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); +SRT_API int setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); +SRT_API int send(SRTSOCKET u, const char* buf, int len, int flags); +SRT_API int recv(SRTSOCKET u, char* buf, int len, int flags); + +SRT_API int sendmsg(SRTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, int64_t srctime = 0); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len, uint64_t& srctime); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len); + +SRT_API int64_t sendfile(SRTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile(SRTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); +SRT_API int64_t sendfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); // select and selectEX are DEPRECATED; please use epoll. -UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); -UDT_API int selectEx(const std::vector& fds, std::vector* readfds, - std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - -UDT_API int epoll_create(); -UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_remove_usock(int eid, UDTSOCKET u); -UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s); -UDT_API int epoll_update_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, +SRT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); +SRT_API int selectEx(const std::vector& fds, std::vector* readfds, + std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); + +SRT_API int epoll_create(); +SRT_API int epoll_add_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_remove_usock(int eid, SRTSOCKET u); +SRT_API int epoll_remove_ssock(int eid, SYSSOCKET s); +SRT_API int epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds = NULL, std::set* wrfds = NULL); -UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut, +SRT_API int epoll_wait2(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL); -UDT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); -UDT_API int epoll_release(int eid); -UDT_API ERRORINFO& getlasterror(); -UDT_API int getlasterror_code(); -UDT_API const char* getlasterror_desc(); -UDT_API int bstats(UDTSOCKET u, TRACEBSTATS* perf, bool clear = true); -UDT_API SRT_SOCKSTATUS getsockstate(UDTSOCKET u); - -// This is a C++ SRT API extension. This is not a part of legacy UDT API. -UDT_API void setloglevel(srt_logging::LogLevel::type ll); -UDT_API void addlogfa(srt_logging::LogFA fa); -UDT_API void dellogfa(srt_logging::LogFA fa); -UDT_API void resetlogfa(std::set fas); -UDT_API void resetlogfa(const int* fara, size_t fara_size); -UDT_API void setlogstream(std::ostream& stream); -UDT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); -UDT_API void setlogflags(int flags); - -UDT_API bool setstreamid(UDTSOCKET u, const std::string& sid); -UDT_API std::string getstreamid(UDTSOCKET u); +SRT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +SRT_API int epoll_release(int eid); +SRT_API ERRORINFO& getlasterror(); +SRT_API int getlasterror_code(); +SRT_API const char* getlasterror_desc(); +SRT_API int bstats(SRTSOCKET u, SRT_TRACEBSTATS* perf, bool clear = true); +SRT_API SRT_SOCKSTATUS getsockstate(SRTSOCKET u); } // namespace UDT @@ -405,7 +226,47 @@ UDT_API std::string getstreamid(UDTSOCKET u); // own logger FA objects, or create their own. The object of this type // is required to initialize the logger FA object. namespace srt_logging { struct LogConfig; } -UDT_API extern srt_logging::LogConfig srt_logger_config; +SRT_API extern srt_logging::LogConfig srt_logger_config; + +namespace srt +{ + +// This is a C++ SRT API extension. This is not a part of legacy UDT API. +SRT_API void setloglevel(srt_logging::LogLevel::type ll); +SRT_API void addlogfa(srt_logging::LogFA fa); +SRT_API void dellogfa(srt_logging::LogFA fa); +SRT_API void resetlogfa(std::set fas); +SRT_API void resetlogfa(const int* fara, size_t fara_size); +SRT_API void setlogstream(std::ostream& stream); +SRT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +SRT_API void setlogflags(int flags); + +SRT_API bool setstreamid(SRTSOCKET u, const std::string& sid); +SRT_API std::string getstreamid(SRTSOCKET u); + +// Namespace alias +namespace logging { + using namespace srt_logging; +} + +} // namespace srt + +// Planned deprecated removal: rel1.6.0 +// There's also no portable way possible to enforce a deprecation +// compiler warning, so leaving as is. +namespace UDT +{ + // Backward-compatible aliases, just for a case someone was using it. + using srt::setloglevel; + using srt::addlogfa; + using srt::dellogfa; + using srt::resetlogfa; + using srt::setlogstream; + using srt::setloghandler; + using srt::setlogflags; + using srt::setstreamid; + using srt::getstreamid; +} #endif /* __cplusplus */ diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/utilities.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/utilities.h new file mode 100644 index 000000000..31e05b205 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/utilities.h @@ -0,0 +1,1098 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_UTILITIES_H +#define INC_SRT_UTILITIES_H + +// Windows warning disabler +#define _CRT_SECURE_NO_WARNINGS 1 + +#include "platform_sys.h" +#include "srt_attr_defs.h" // defines HAVE_CXX11 + +// Happens that these are defined, undefine them in advance +#undef min +#undef max + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_CXX11 +#include +#endif + +#include +#include +#include +#include + +// -------------- UTILITIES ------------------------ + +// --- ENDIAN --- +// Copied from: https://gist.github.com/panzi/6856583 +// License: Public Domain. + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) + +# include + +// GLIBC-2.8 and earlier does not provide these macros. +// See http://linux.die.net/man/3/endian +// From https://gist.github.com/panzi/6856583 +# if defined(__GLIBC__) \ + && ( !defined(__GLIBC_MINOR__) \ + || ((__GLIBC__ < 2) \ + || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) ) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + +# define htole32(x) (x) +# define le32toh(x) (x) + +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) + +# define htole16(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) +# define le16toh(x) ((((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) + +# define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) +# define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) + +# else +# error Byte Order not supported or not defined. +# endif +# endif + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + +# include + +#ifndef be16toh +# define be16toh(x) betoh16(x) +#endif +#ifndef le16toh +# define le16toh(x) letoh16(x) +#endif + +#ifndef be32toh +# define be32toh(x) betoh32(x) +#endif +#ifndef le32toh +# define le32toh(x) letoh32(x) +#endif + +#ifndef be64toh +# define be64toh(x) betoh64(x) +#endif +#ifndef le64toh +# define le64toh(x) letoh64(x) +#endif + +#elif defined(SUNOS) + + // SunOS/Solaris + + #include + #include + + #define __LITTLE_ENDIAN 1234 + #define __BIG_ENDIAN 4321 + + # if defined(_BIG_ENDIAN) + #define __BYTE_ORDER __BIG_ENDIAN + #define be64toh(x) (x) + #define be32toh(x) (x) + #define be16toh(x) (x) + #define le16toh(x) ((uint16_t)BSWAP_16(x)) + #define le32toh(x) BSWAP_32(x) + #define le64toh(x) BSWAP_64(x) + #define htobe16(x) (x) + #define htole16(x) ((uint16_t)BSWAP_16(x)) + #define htobe32(x) (x) + #define htole32(x) BSWAP_32(x) + #define htobe64(x) (x) + #define htole64(x) BSWAP_64(x) + # else + #define __BYTE_ORDER __LITTLE_ENDIAN + #define be64toh(x) BSWAP_64(x) + #define be32toh(x) ntohl(x) + #define be16toh(x) ntohs(x) + #define le16toh(x) (x) + #define le32toh(x) (x) + #define le64toh(x) (x) + #define htobe16(x) htons(x) + #define htole16(x) (x) + #define htobe32(x) htonl(x) + #define htole32(x) (x) + #define htobe64(x) BSWAP_64(x) + #define htole64(x) (x) + # endif + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error Endian: platform not supported + +#endif + +// Hardware <--> Network (big endian) convention +inline void HtoNLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htonl(src[i]); +} + +inline void NtoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = ntohl(src[i]); +} + +// Hardware <--> Intel (little endian) convention +inline void HtoILA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = htole32(src[i]); +} + +inline void ItoHLA(uint32_t* dst, const uint32_t* src, size_t size) +{ + for (size_t i = 0; i < size; ++ i) + dst[i] = le32toh(src[i]); +} + +// Bit numbering utility. +// +// This is something that allows you to turn 32-bit integers into bit fields. +// Although bitfields are part of C++ language, they are not designed to be +// interchanged with 32-bit numbers, and any attempt to doing it (by placing +// inside a union, for example) is nonportable (order of bitfields inside +// same-covering 32-bit integer number is dependent on the endian), so they are +// popularly disregarded as useless. Instead the 32-bit numbers with bits +// individually selected is preferred, with usually manual playing around with +// & and | operators, as well as << and >>. This tool is designed to simplify +// the use of them. This can be used to qualify a range of bits inside a 32-bit +// number to be a separate number, you can "wrap" it by placing the integer +// value in the range of these bits, as well as "unwrap" (extract) it from +// the given place. For your own safety, use one prefix to all constants that +// concern bit ranges intended to be inside the same "bit container". +// +// Usage: typedef Bits MASKTYPE; // MASKTYPE is a name of your choice. +// +// With this defined, you can use the following members: +// - MASKTYPE::mask - to get the int32_t value with bimask (used bits set to 1, others to 0) +// - MASKTYPE::offset - to get the lowermost bit number, or number of bits to shift +// - MASKTYPE::wrap(int value) - to create a bitset where given value is encoded in given bits +// - MASKTYPE::unwrap(int bitset) - to extract an integer value from the bitset basing on mask definition +// (rightmost defaults to leftmost) +// REMEMBER: leftmost > rightmost because bit 0 is the LEAST significant one! + +template +struct BitsetMask +{ + static const bool correct = L >= R; + static const uint32_t value = (1u << L) | BitsetMask::value; +}; + +// This is kind-of functional programming. This describes a special case that is +// a "terminal case" in case when decreased L-1 (see above) reached == R. +template +struct BitsetMask +{ + static const bool correct = true; + static const uint32_t value = 1u << R; +}; + +// This is a trap for a case that BitsetMask::correct in the master template definition +// evaluates to false. This trap causes compile error and prevents from continuing +// recursive unwinding in wrong direction (and challenging the compiler's resistiveness +// for infinite loops). +template +struct BitsetMask +{ +}; + +template +struct Bits +{ + // DID YOU GET a kind-of error: 'mask' is not a member of 'Bits<3u, 5u, false>'? + // See the the above declaration of 'correct'! + static const uint32_t mask = BitsetMask::value; + static const uint32_t offset = R; + static const size_t size = L - R + 1; + + // Example: if our bitset mask is 00111100, this checks if given value fits in + // 00001111 mask (that is, does not exceed <0, 15>. + static bool fit(uint32_t value) { return (BitsetMask::value & value) == value; } + + /// 'wrap' gets some given value that should be placed in appropriate bit range and + /// returns a whole 32-bit word that has the value already at specified place. + /// To create a 32-bit container that contains already all values destined for different + /// bit ranges, simply use wrap() for each of them and bind them with | operator. + static uint32_t wrap(uint32_t baseval) { return (baseval << offset) & mask; } + + /// Extracts appropriate bit range and returns them as normal integer value. + static uint32_t unwrap(uint32_t bitset) { return (bitset & mask) >> offset; } + + template + static T unwrapt(uint32_t bitset) { return static_cast(unwrap(bitset)); } +}; + + +//inline int32_t Bit(size_t b) { return 1 << b; } +// XXX This would work only with 'constexpr', but this is +// available only in C++11. In C++03 this can be only done +// using a macro. +// +// Actually this can be expressed in C++11 using a better technique, +// such as user-defined literals: +// 2_bit --> 1 >> 2 + +#ifdef BIT +#undef BIT +#endif +#define BIT(x) (1 << (x)) + + +// ------------------------------------------------------------ +// This is something that reminds a structure consisting of fields +// of the same type, implemented as an array. It's parametrized +// by the type of fields and the type, which's values should be +// used for indexing (preferably an enum type). Whatever type is +// used for indexing, it is converted to size_t for indexing the +// actual array. +// +// The user should use it as an array: ds[DS_NAME], stating +// that DS_NAME is of enum type passed as 3rd parameter. +// However trying to do ds[0] would cause a compile error. +template +struct DynamicStruct +{ + FieldType inarray[NoOfFields]; + + void clear() + { + // As a standard library, it can be believed that this call + // can be optimized when FieldType is some integer. + std::fill(inarray, inarray + NoOfFields, FieldType()); + } + + FieldType operator[](IndexerType ix) const { return inarray[size_t(ix)]; } + FieldType& operator[](IndexerType ix) { return inarray[size_t(ix)]; } + + template + FieldType operator[](AnyOther ix) const + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + template + FieldType& operator[](AnyOther ix) + { + // If you can see a compile error here ('int' is not a class or struct, or + // that there's no definition of 'type' in given type), it means that you + // have used invalid data type passed to [] operator. See the definition + // of this type as DynamicStruct and see which type is required for indexing. + typename AnyOther::type wrong_usage_of_operator_index = AnyOther::type; + return inarray[size_t(ix)]; + } + + operator FieldType* () { return inarray; } + operator const FieldType* () const { return inarray; } + + char* raw() { return (char*)inarray; } +}; + + +/// Fixed-size array template class. +namespace srt { + +template +class FixedArray +{ +public: + FixedArray(size_t size) + : m_size(size) + , m_entries(new T[size]) + { + } + + ~FixedArray() + { + delete [] m_entries; + } + +public: + const T& operator[](size_t index) const + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](size_t index) + { + if (index >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + const T& operator[](int index) const + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + T& operator[](int index) + { + if (index < 0 || static_cast(index) >= m_size) + raise_expection(index); + + return m_entries[index]; + } + + size_t size() const { return m_size; } + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin() { return m_entries; } + iterator end() { return m_entries + m_size; } + + const_iterator cbegin() const { return m_entries; } + const_iterator cend() const { return m_entries + m_size; } + + T* data() { return m_entries; } + +private: + FixedArray(const FixedArray& ); + FixedArray& operator=(const FixedArray&); + + void raise_expection(int i) const + { + std::stringstream ss; + ss << "Index " << i << "out of range"; + throw std::runtime_error(ss.str()); + } + +private: + size_t m_size; + T* const m_entries; +}; + +} // namespace srt + +// ------------------------------------------------------------ + + + +inline bool IsSet(int32_t bitset, int32_t flagset) +{ + return (bitset & flagset) == flagset; +} + +// std::addressof in C++11, +// needs to be provided for C++03 +template +inline RefType* AddressOf(RefType& r) +{ + return (RefType*)(&(unsigned char&)(r)); +} + +template +struct explicit_t +{ + T inobject; + explicit_t(const T& uo): inobject(uo) {} + + operator T() const { return inobject; } + +private: + template + explicit_t(const X& another); +}; + +// This is required for Printable function if you have a container of pairs, +// but this function has a different definition for C++11 and C++03. +namespace srt_pair_op +{ + template + std::ostream& operator<<(std::ostream& s, const std::pair& v) + { + s << "{" << v.first << " " << v.second << "}"; + return s; + } +} + +#if HAVE_CXX11 + +template +inline auto Move(In& i) -> decltype(std::move(i)) { return std::move(i); } + +// Gluing string of any type, wrapper for operator << + +template +inline Stream& Print(Stream& in) { return in;} + +template +inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args) +{ + sout << arg1; + return Print(sout, args...); +} + +template +inline std::string Sprint(Args&&... args) +{ + std::ostringstream sout; + Print(sout, args...); + return sout.str(); +} + +// We need to use UniquePtr, in the form of C++03 it will be a #define. +// Naturally will be used std::move() so that it can later painlessly +// switch to C++11. +template +using UniquePtr = std::unique_ptr; + +template inline +std::string Printable(const Container& in, Value /*pseudoargument*/, Args&&... args) +{ + using namespace srt_pair_op; + std::ostringstream os; + Print(os, args...); + os << "[ "; + for (auto i: in) + os << Value(i) << " "; + os << "]"; + return os.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + using Value = typename Container::value_type; + return Printable(in, Value()); +} + +template +auto map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) -> typename Map::mapped_type +{ + auto it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +auto map_getp(Map& m, const Key& key) -> typename Map::mapped_type* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + +template +auto map_getp(const Map& m, const Key& key) -> typename Map::mapped_type const* +{ + auto it = m.find(key); + return it == m.end() ? nullptr : std::addressof(it->second); +} + + +#else + +// The unique_ptr requires C++11, and the rvalue-reference feature, +// so here we're simulate the behavior using the old std::auto_ptr. + +// This is only to make a "move" call transparent and look ok towards +// the C++11 code. +template +std::auto_ptr_ref Move(const std::auto_ptr_ref& in) { return in; } + +// We need to provide also some fixes for this type that were not present in auto_ptr, +// but they are present in unique_ptr. + +// C++03 doesn't have a templated typedef, but still we need some things +// that can only function as a class. +template +class UniquePtr: public std::auto_ptr +{ + typedef std::auto_ptr Base; + +public: + + // This is a template - so method names must be declared explicitly + typedef typename Base::element_type element_type; + using Base::get; + using Base::reset; + + // All constructor declarations must be repeated. + // "Constructor delegation" is also only C++11 feature. + explicit UniquePtr(element_type* p = 0) throw() : Base(p) {} + UniquePtr(UniquePtr& a) throw() : Base(a) { } + template + UniquePtr(UniquePtr& a) throw() : Base(a) {} + + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + template + UniquePtr& operator=(UniquePtr& a) throw() { return Base::operator=(a); } + + // Good, now we need to add some parts of the API of unique_ptr. + + bool operator==(const UniquePtr& two) const { return get() == two.get(); } + bool operator!=(const UniquePtr& two) const { return get() != two.get(); } + + bool operator==(const element_type* two) const { return get() == two; } + bool operator!=(const element_type* two) const { return get() != two; } + + operator bool () { return 0!= get(); } +}; + +// A primitive one-argument versions of Sprint and Printable +template +inline std::string Sprint(const Arg1& arg) +{ + std::ostringstream sout; + sout << arg; + return sout.str(); +} + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator i = in.begin(); i != in.end(); ++i) + os << Value(*i) << " "; + os << "]"; + + return os.str(); +} + +template +typename Map::mapped_type map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type map_get(const Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? def : it->second; +} + +template +typename Map::mapped_type* map_getp(Map& m, const Key& key) +{ + typename Map::iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +template +typename Map::mapped_type const* map_getp(const Map& m, const Key& key) +{ + typename Map::const_iterator it = m.find(key); + return it == m.end() ? (typename Map::mapped_type*)0 : &(it->second); +} + +#endif + +// Printable with prefix added for every element. +// Useful when printing a container of sockets or sequence numbers. +template inline +std::string PrintableMod(const Container& in, const std::string& prefix) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + std::ostringstream os; + os << "[ "; + for (typename Container::const_iterator y = in.begin(); y != in.end(); ++y) + os << prefix << Value(*y) << " "; + os << "]"; + return os.str(); +} + +template +inline void FilterIf(InputIterator bg, InputIterator nd, + OutputIterator out, TransFunction fn) +{ + for (InputIterator i = bg; i != nd; ++i) + { + std::pair result = fn(*i); + if (!result.second) + continue; + *out++ = result.first; + } +} + +template +inline void insert_uniq(std::vector& v, const ArgValue& val) +{ + typename std::vector::iterator i = std::find(v.begin(), v.end(), val); + if (i != v.end()) + return; + + v.push_back(val); +} + +template +struct CallbackHolder +{ + void* opaque; + Signature* fn; + + CallbackHolder(): opaque(NULL), fn(NULL) {} + + void set(void* o, Signature* f) + { + // Test if the pointer is a pointer to function. Don't let + // other type of pointers here. +#if HAVE_CXX11 + static_assert(std::is_function::value, "CallbackHolder is for functions only!"); +#else + // This is a poor-man's replacement, which should in most compilers + // generate a warning, if `Signature` resolves to a value type. + // This would make an illegal pointer cast from a value to a function type. + // Casting function-to-function, however, should not. Unfortunately + // newer compilers disallow that, too (when a signature differs), but + // then they should better use the C++11 way, much more reliable and safer. + void* (*testfn)(void*) = (void*(*)(void*))f; + (void)(testfn); +#endif + opaque = o; + fn = f; + } + + operator bool() { return fn != NULL; } +}; + +#define CALLBACK_CALL(holder,...) (*holder.fn)(holder.opaque, __VA_ARGS__) + +inline std::string FormatBinaryString(const uint8_t* bytes, size_t size) +{ + if ( size == 0 ) + return ""; + + //char buf[256]; + using namespace std; + + ostringstream os; + + // I know, it's funny to use sprintf and ostringstream simultaneously, + // but " %02X" in iostream is: << " " << hex << uppercase << setw(2) << setfill('0') << VALUE << setw(1) + // Too noisy. OTOH ostringstream solves the problem of memory allocation + // for a string of unpredictable size. + //sprintf(buf, "%02X", int(bytes[0])); + + os.fill('0'); + os.width(2); + os.setf(ios::basefield, ios::hex); + os.setf(ios::uppercase); + + //os << buf; + os << int(bytes[0]); + + + for (size_t i = 1; i < size; ++i) + { + //sprintf(buf, " %02X", int(bytes[i])); + //os << buf; + os << int(bytes[i]); + } + return os.str(); +} + + +/// This class is useful in every place where +/// the time drift should be traced. It's currently in use in every +/// solution that implements any kind of TSBPD. +template +class DriftTracer +{ + int64_t m_qDrift; + int64_t m_qOverdrift; + + int64_t m_qDriftSum; + unsigned m_uDriftSpan; + +public: + DriftTracer() + : m_qDrift(0) + , m_qOverdrift(0) + , m_qDriftSum(0) + , m_uDriftSpan(0) + {} + + bool update(int64_t driftval) + { + m_qDriftSum += driftval; + ++m_uDriftSpan; + + // I moved it here to calculate accumulated overdrift. + if (CLEAR_ON_UPDATE) + m_qOverdrift = 0; + + if (m_uDriftSpan < MAX_SPAN) + return false; + + + // Calculate the median of all drift values. + // In most cases, the divisor should be == MAX_SPAN. + m_qDrift = m_qDriftSum / m_uDriftSpan; + + // And clear the collection + m_qDriftSum = 0; + m_uDriftSpan = 0; + + // In case of "overdrift", save the overdriven value in 'm_qOverdrift'. + // In clear mode, you should add this value to the time base when update() + // returns true. The drift value will be since now measured with the + // overdrift assumed to be added to the base. + if (std::abs(m_qDrift) > MAX_DRIFT) + { + m_qOverdrift = m_qDrift < 0 ? -MAX_DRIFT : MAX_DRIFT; + m_qDrift -= m_qOverdrift; + } + + // printDriftOffset(m_qOverdrift, m_qDrift); + + // Timebase is separate + // m_qTimeBase += m_qOverdrift; + + return true; + } + + // For group overrides + void forceDrift(int64_t driftval) + { + m_qDrift = driftval; + } + + // These values can be read at any time, however if you want + // to depend on the fact that they have been changed lately, + // you have to check the return value from update(). + // + // IMPORTANT: drift() can be called at any time, just remember + // that this value may look different than before only if the + // last update() returned true, which need not be important for you. + // + // CASE: CLEAR_ON_UPDATE = true + // overdrift() should be read only immediately after update() returned + // true. It will stay available with this value until the next time when + // update() returns true, in which case the value will be cleared. + // Therefore, after calling update() if it retuns true, you should read + // overdrift() immediately an make some use of it. Next valid overdrift + // will be then relative to every previous overdrift. + // + // CASE: CLEAR_ON_UPDATE = false + // overdrift() will start from 0, but it will always keep track on + // any changes in overdrift. By manipulating the MAX_DRIFT parameter + // you can decide how high the drift can go relatively to stay below + // overdrift. + int64_t drift() const { return m_qDrift; } + int64_t overdrift() const { return m_qOverdrift; } +}; + +template +struct MapProxy +{ + std::map& mp; + const KeyType& key; + + MapProxy(std::map& m, const KeyType& k): mp(m), key(k) {} + + void operator=(const ValueType& val) + { + mp[key] = val; + } + + typename std::map::iterator find() + { + return mp.find(key); + } + + typename std::map::const_iterator find() const + { + return mp.find(key); + } + + operator ValueType() const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return ""; + return p->second; + } + + ValueType deflt(const ValueType& defval) const + { + typename std::map::const_iterator p = find(); + if (p == mp.end()) + return defval; + return p->second; + } + + bool exists() const + { + return find() != mp.end(); + } +}; + +/// Print some hash-based stamp of the first 16 bytes in the buffer +inline std::string BufferStamp(const char* mem, size_t size) +{ + using namespace std; + char spread[16]; + + if (size < 16) + memset((spread + size), 0, 16 - size); + memcpy((spread), mem, min(size_t(16), size)); + + // Now prepare 4 cells for uint32_t. + union + { + uint32_t sum; + char cells[4]; + }; + memset((cells), 0, 4); + + for (size_t x = 0; x < 4; ++x) + for (size_t y = 0; y < 4; ++y) + { + cells[x] += spread[x+4*y]; + } + + // Convert to hex string + ostringstream os; + os << hex << uppercase << setfill('0') << setw(8) << sum; + + return os.str(); +} + +template +inline void Split(const std::string & str, char delimiter, OutputIterator tokens) +{ + if ( str.empty() ) + return; // May cause crash and won't extract anything anyway + + std::size_t start; + std::size_t end = -1; + + do + { + start = end + 1; + end = str.find(delimiter, start); + *tokens = str.substr( + start, + (end == std::string::npos) ? std::string::npos : end - start); + ++tokens; + } while (end != std::string::npos); +} + +inline std::string SelectNot(const std::string& unwanted, const std::string& s1, const std::string& s2) +{ + if (s1 == unwanted) + return s2; // might be unwanted, too, but then, there's nothing you can do anyway + if (s2 == unwanted) + return s1; + + // Both have wanted values, so now compare if they are same + if (s1 == s2) + return s1; // occasionally there's a winner + + // Irresolvable situation. + return std::string(); +} + +inline std::string SelectDefault(const std::string& checked, const std::string& def) +{ + if (checked == "") + return def; + return checked; +} + +template +inline size_t safe_advance(It& it, size_t num, It end) +{ + while ( it != end && num ) + { + --num; + ++it; + } + + return num; // will be effectively 0, if reached the required point, or >0, if end was by that number earlier +} + +// This is available only in C++17, dunno why not C++11 as it's pretty useful. +template inline +ATR_CONSTEXPR size_t Size(const V (&)[N]) ATR_NOEXCEPT { return N; } + +template +inline ValueType avg_iir(ValueType old_value, ValueType new_value) +{ + return (old_value * (DEPRLEN - 1) + new_value) / DEPRLEN; +} + +template +inline ValueType avg_iir_w(ValueType old_value, ValueType new_value, size_t new_val_weight) +{ + return (old_value * (DEPRLEN - new_val_weight) + new_value * new_val_weight) / DEPRLEN; +} + +// Property accessor definitions +// +// "Property" is a special method that accesses given field. +// This relies only on a convention, which is the following: +// +// V x = object.prop(); <-- get the property's value +// object.prop(x); <-- set the property a value +// +// Properties might be also chained when setting: +// +// object.prop1(v1).prop2(v2).prop3(v3); +// +// Properties may be defined various even very complicated +// ways, which is simply providing a method with body. In order +// to define a property simplest possible way, that is, refer +// directly to the field that keeps it, here are the following macros: +// +// Prefix: SRTU_PROPERTY_ +// Followed by: +// - access type: RO, WO, RW, RR, RRW +// - chain flag: optional _CHAIN +// Where access type is: +// - RO - read only. Defines reader accessor. The accessor method will be const. +// - RR - read reference. The accessor isn't const to allow reference passthrough. +// - WO - write only. Defines writer accessor. +// - RW - combines RO and WO. +// - RRW - combines RR and WO. +// +// The _CHAIN marker is optional for macros providing writable accessors +// for properties. The difference is that while simple write accessors return +// void, the chaining accessors return the reference to the object for which +// the write accessor was called so that you can call the next accessor (or +// any other method as well) for the result. + +#define SRTU_PROPERTY_RR(type, name, field) type name() { return field; } +#define SRTU_PROPERTY_RO(type, name, field) type name() const { return field; } +#define SRTU_PROPERTY_WO(type, name, field) void set_##name(type arg) { field = arg; } +#define SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) otype& set_##name(type arg) { field = arg; return *this; } +#define SRTU_PROPERTY_RW(type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RRW(type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO(type, name, field) +#define SRTU_PROPERTY_RW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RO(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) +#define SRTU_PROPERTY_RRW_CHAIN(otype, type, name, field) SRTU_PROPERTY_RR(type, name, field); SRTU_PROPERTY_WO_CHAIN(otype, type, name, field) + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/version.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/version.h index 7033968e8..b2773dd3b 100644 --- a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/version.h +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/version.h @@ -23,10 +23,10 @@ written by #define SRT_VERSION_MAJOR 1 #define SRT_VERSION_MINOR 5 -#define SRT_VERSION_PATCH 1 +#define SRT_VERSION_PATCH 3 /* #undef SRT_VERSION_BUILD */ -#define SRT_VERSION_STRING "1.5.1" +#define SRT_VERSION_STRING "1.5.3" #define SRT_VERSION_VALUE \ SRT_MAKE_VERSION_VALUE( \ SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH ) diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/window.h b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/window.h new file mode 100644 index 000000000..ecc4a4947 --- /dev/null +++ b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/Headers/window.h @@ -0,0 +1,355 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/22/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +#ifndef INC_SRT_WINDOW_H +#define INC_SRT_WINDOW_H + + +#ifndef _WIN32 + #include + #include +#endif +#include "packet.h" +#include "udt.h" + +namespace srt +{ + +namespace ACKWindowTools +{ + struct Seq + { + int32_t iACKSeqNo; // Seq. No. of the ACK packet + int32_t iACK; // Data packet Seq. No. carried by the ACK packet + sync::steady_clock::time_point tsTimeStamp; // The timestamp when the ACK was sent + }; + + void store(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t ack); + int acknowledge(Seq* r_aSeq, const size_t size, int& r_iHead, int& r_iTail, int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime); +} + +template +class CACKWindow +{ +public: + CACKWindow() : + m_aSeq(), + m_iHead(0), + m_iTail(0) + { + m_aSeq[0].iACKSeqNo = SRT_SEQNO_NONE; + } + + ~CACKWindow() {} + + /// Write an ACK record into the window. + /// @param [in] seq Seq. No. of the ACK packet + /// @param [in] ack Data packet Seq. No. carried by the ACK packet + + void store(int32_t seq, int32_t ack) + { + return ACKWindowTools::store(m_aSeq, SIZE, m_iHead, m_iTail, seq, ack); + } + + /// Search the ACKACK "seq" in the window, find out the data packet "ack" + /// and calculate RTT estimate based on the ACK/ACKACK pair + /// @param [in] seq Seq. No. of the ACK packet carried within ACKACK + /// @param [out] ack Acknowledged data packet Seq. No. from the ACK packet that matches the ACKACK + /// @param [in] currtime The timestamp of ACKACK packet reception by the receiver + /// @return RTT + + int acknowledge(int32_t seq, int32_t& r_ack, const sync::steady_clock::time_point& currtime) + { + return ACKWindowTools::acknowledge(m_aSeq, SIZE, m_iHead, m_iTail, seq, r_ack, currtime); + } + +private: + + typedef ACKWindowTools::Seq Seq; + + Seq m_aSeq[SIZE]; + int m_iHead; // Pointer to the latest ACK record + int m_iTail; // Pointer to the oldest ACK record + +private: + CACKWindow(const CACKWindow&); + CACKWindow& operator=(const CACKWindow&); +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CPktTimeWindowTools +{ +public: + static int getPktRcvSpeed_in(const int* window, int* replica, const int* bytes, size_t asize, int& bytesps); + static int getBandwidth_in(const int* window, int* replica, size_t psize); + + static void initializeWindowArrays(int* r_pktWindow, int* r_probeWindow, int* r_bytesWindow, size_t asize, size_t psize); +}; + +template +class CPktTimeWindow: CPktTimeWindowTools +{ +public: + CPktTimeWindow(): + m_aPktWindow(), + m_aBytesWindow(), + m_iPktWindowPtr(0), + m_aProbeWindow(), + m_iProbeWindowPtr(0), + m_iLastSentTime(0), + m_iMinPktSndInt(1000000), + m_tsLastArrTime(sync::steady_clock::now()), + m_tsCurrArrTime(), + m_tsProbeTime(), + m_Probe1Sequence(SRT_SEQNO_NONE) + { + // Exception: up to CUDT ctor + sync::setupMutex(m_lockPktWindow, "PktWindow"); + sync::setupMutex(m_lockProbeWindow, "ProbeWindow"); + CPktTimeWindowTools::initializeWindowArrays(m_aPktWindow, m_aProbeWindow, m_aBytesWindow, ASIZE, PSIZE); + } + + ~CPktTimeWindow() + { + } + +public: + /// read the minimum packet sending interval. + /// @return minimum packet sending interval (microseconds). + + int getMinPktSndInt() const { return m_iMinPktSndInt; } + + /// Calculate the packets arrival speed. + /// @return Packet arrival speed (packets per second). + + int getPktRcvSpeed(int& w_bytesps) const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockPktWindow); + + int pktReplica[ASIZE]; // packet information window (inter-packet time) + return getPktRcvSpeed_in(m_aPktWindow, pktReplica, m_aBytesWindow, ASIZE, (w_bytesps)); + } + + int getPktRcvSpeed() const + { + int bytesps; + return getPktRcvSpeed((bytesps)); + } + + /// Estimate the bandwidth. + /// @return Estimated bandwidth (packets per second). + + int getBandwidth() const + { + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + int probeReplica[PSIZE]; + return getBandwidth_in(m_aProbeWindow, probeReplica, PSIZE); + } + + /// Record time information of a packet sending. + /// @param currtime timestamp of the packet sending. + + void onPktSent(int currtime) + { + int interval = currtime - m_iLastSentTime; + + if ((interval < m_iMinPktSndInt) && (interval > 0)) + m_iMinPktSndInt = interval; + + m_iLastSentTime = currtime; + } + + /// Record time information of an arrived packet. + + void onPktArrival(int pktsz = 0) + { + sync::ScopedLock cg(m_lockPktWindow); + + m_tsCurrArrTime = sync::steady_clock::now(); + + // record the packet interval between the current and the last one + m_aPktWindow[m_iPktWindowPtr] = (int) sync::count_microseconds(m_tsCurrArrTime - m_tsLastArrTime); + m_aBytesWindow[m_iPktWindowPtr] = pktsz; + + // the window is logically circular + ++ m_iPktWindowPtr; + if (m_iPktWindowPtr == ASIZE) + m_iPktWindowPtr = 0; + + // remember last packet arrival time + m_tsLastArrTime = m_tsCurrArrTime; + } + + /// Shortcut to test a packet for possible probe 1 or 2 + void probeArrival(const CPacket& pkt, bool unordered) + { + const int inorder16 = pkt.m_iSeqNo & PUMASK_SEQNO_PROBE; + + // for probe1, we want 16th packet + if (inorder16 == 0) + { + probe1Arrival(pkt, unordered); + } + + if (unordered) + return; + + // for probe2, we want 17th packet + if (inorder16 == 1) + { + probe2Arrival(pkt); + } + } + + /// Record the arrival time of the first probing packet. + void probe1Arrival(const CPacket& pkt, bool unordered) + { + if (unordered && pkt.m_iSeqNo == m_Probe1Sequence) + { + // Reset the starting probe into "undefined", when + // a packet has come as retransmitted before the + // measurement at arrival of 17th could be taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + return; + } + + m_tsProbeTime = sync::steady_clock::now(); + m_Probe1Sequence = pkt.m_iSeqNo; // Record the sequence where 16th packet probe was taken + } + + /// Record the arrival time of the second probing packet and the interval between packet pairs. + + void probe2Arrival(const CPacket& pkt) + { + // Reject probes that don't refer to the very next packet + // towards the one that was lately notified by probe1Arrival. + // Otherwise the result can be stupid. + + // Simply, in case when this wasn't called exactly for the + // expected packet pair, behave as if the 17th packet was lost. + + // no start point yet (or was reset) OR not very next packet + if (m_Probe1Sequence == SRT_SEQNO_NONE || CSeqNo::incseq(m_Probe1Sequence) != pkt.m_iSeqNo) + return; + + // Grab the current time before trying to acquire + // a mutex. This might add extra delay and therefore + // screw up the measurement. + const sync::steady_clock::time_point now = sync::steady_clock::now(); + + // Lock access to the packet Window + sync::ScopedLock cg(m_lockProbeWindow); + + m_tsCurrArrTime = now; + + // Reset the starting probe to prevent checking if the + // measurement was already taken. + m_Probe1Sequence = SRT_SEQNO_NONE; + + // record the probing packets interval + // Adjust the time for what a complete packet would have take + const int64_t timediff = sync::count_microseconds(m_tsCurrArrTime - m_tsProbeTime); + const int64_t timediff_times_pl_size = timediff * CPacket::SRT_MAX_PAYLOAD_SIZE; + + // Let's take it simpler than it is coded here: + // (stating that a packet has never zero size) + // + // probe_case = (now - previous_packet_time) * SRT_MAX_PAYLOAD_SIZE / pktsz; + // + // Meaning: if the packet is fully packed, probe_case = timediff. + // Otherwise the timediff will be "converted" to a time that a fully packed packet "would take", + // provided the arrival time is proportional to the payload size and skipping + // the ETH+IP+UDP+SRT header part elliminates the constant packet delivery time influence. + // + const size_t pktsz = pkt.getLength(); + m_aProbeWindow[m_iProbeWindowPtr] = pktsz ? int(timediff_times_pl_size / pktsz) : int(timediff); + + // OLD CODE BEFORE BSTATS: + // record the probing packets interval + // m_aProbeWindow[m_iProbeWindowPtr] = int(m_tsCurrArrTime - m_tsProbeTime); + + // the window is logically circular + ++ m_iProbeWindowPtr; + if (m_iProbeWindowPtr == PSIZE) + m_iProbeWindowPtr = 0; + } + +private: + int m_aPktWindow[ASIZE]; // Packet information window (inter-packet time) + int m_aBytesWindow[ASIZE]; + int m_iPktWindowPtr; // Position pointer of the packet info. window + mutable sync::Mutex m_lockPktWindow; // Used to synchronize access to the packet window + + int m_aProbeWindow[PSIZE]; // Record inter-packet time for probing packet pairs + int m_iProbeWindowPtr; // Position pointer to the probing window + mutable sync::Mutex m_lockProbeWindow; // Used to synchronize access to the probe window + + int m_iLastSentTime; // Last packet sending time + int m_iMinPktSndInt; // Minimum packet sending interval + + sync::steady_clock::time_point m_tsLastArrTime; // Last packet arrival time + sync::steady_clock::time_point m_tsCurrArrTime; // Current packet arrival time + sync::steady_clock::time_point m_tsProbeTime; // Arrival time of the first probing packet + int32_t m_Probe1Sequence; // Sequence number for which the arrival time was notified + +private: + CPktTimeWindow(const CPktTimeWindow&); + CPktTimeWindow &operator=(const CPktTimeWindow&); +}; + +} // namespace srt + +#endif diff --git a/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/libsrt.a b/Vendor/SRT/libsrt.xcframework/macos-arm64_x86_64/libsrt.a index 348913d6bc34025438954e9203fffa03df5b3619..b255d642468ca510a99b9aea119504a6beb84234 100644 GIT binary patch delta 860 zcmW;J=bs1!0Eh8U>5x=Z>XhW7g(MkWqEMs|6-6jYdB`diMRjPHP1-|b<*Wup zMan3<(l%au+3(Yf??3Q7$M;uMIUX~+RVpqno?B8_t*`_+K~9uPa*`BCWvL=n5i(Ln$;0x9jFv~`F?n3Z$XIzoo|JJiUY?StqNC`FJ7b#*6V%%!~Q)a=a3+ z#%u9zuH z8|z|yd={U_7x86mh>h`8d>xx&b9@uu#&@wLw#N6dEq;g}V|(m~ov|x^il1Y5?1{ax pFZRcQI2gagukl+Pir?dp_%r^BzvG|yHx9>Rts+~G(va1VlgGFarHoWYi3VMfl9gGM zt*xx6RIk14_vyv=A9$V<`&U*z5mUQVENR|iM)}Z=MWx6|Qb8(8fmD){rLt6!s!~m= zOQD=1HRM#ODYfJ@IbF_>+EPc(l)6$R_2eu$Th5Vll?c_RXFCFB1=_sA#2Dwpg zlAGlg=`6QO7r9Nk%I(rk?vOj>F1cIok$dGn=`Q!n1M;Bske>38^pf7vNBT-X=`RCh zpgb(8H%K0lM`f@)CXdS#@}vxrr(~!Mli@N#M#|Ijj65sP$tZbVMoZ~(#uOC)zofKq zWYPGt;xX|;j16O4jE@O1G0Nh_m=u#^O1ufkY>jR4O?(^MV@K?aU9mg%#NOB!-^KUwL;M&&#n16e o?2ljLw>S_7<4_!qBk_A2jbrgg{2716@%TIbSy5K}@8HS*0T`ip)c^nh diff --git a/Vendor/SRT/module.modulemap b/Vendor/SRT/module.modulemap new file mode 100644 index 000000000..df46f3069 --- /dev/null +++ b/Vendor/SRT/module.modulemap @@ -0,0 +1,4 @@ +module libsrt { + header "srt.h" + export * +}