mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Upgrade libsrt to v1.5.3. v5.0.183 (#3808)
This commit is contained in:
parent
389a62ee3a
commit
632d457194
154 changed files with 39813 additions and 17038 deletions
4
trunk/3rdparty/README.md
vendored
4
trunk/3rdparty/README.md
vendored
|
@ -9,8 +9,8 @@ nginx-1.5.7.zip
|
|||
* for srs to support hls streaming.
|
||||
|
||||
srt-1-fit
|
||||
srt-1.4.1.tar.gz
|
||||
* https://github.com/Haivision/srt/releases/tag/v1.4.1
|
||||
srt-1.5.3.tar.gz
|
||||
* https://github.com/Haivision/srt/releases/tag/v1.5.3
|
||||
* https://ossrs.net/lts/zh-cn/license#srt
|
||||
|
||||
openssl-1.1-fit
|
||||
|
|
882
trunk/3rdparty/srt-1-fit/CMakeLists.txt
vendored
882
trunk/3rdparty/srt-1-fit/CMakeLists.txt
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,63 +0,0 @@
|
|||
#ifndef _WINPORTING_H_
|
||||
#define _WINPORTING_H_
|
||||
|
||||
// NOTE: This file has been borrowed from LCM project
|
||||
// http://lcm-proj.github.io/
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
#define strtoll _strtoi64
|
||||
#define strdup _strdup
|
||||
#define mode_t int
|
||||
#define snprintf _snprintf
|
||||
//#define PATH_MAX MAX_PATH
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
//#define socklen_t int
|
||||
#define in_addr_t in_addr
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#define HUGE HUGE_VAL
|
||||
#define O_NONBLOCK 0x4000
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
#endif
|
||||
|
||||
#include <direct.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Microsoft implementation of these structures has the
|
||||
// pointer and length in reversed positions.
|
||||
typedef struct iovec
|
||||
{
|
||||
ULONG iov_len;
|
||||
char *iov_base;
|
||||
} iovec;
|
||||
|
||||
typedef struct msghdr
|
||||
{
|
||||
struct sockaddr *msg_name;
|
||||
int msg_namelen;
|
||||
struct iovec *msg_iov;
|
||||
ULONG msg_iovlen;
|
||||
int msg_controllen;
|
||||
char *msg_control;
|
||||
ULONG msg_flags;
|
||||
} msghdr;
|
||||
|
||||
//typedef long int ssize_t;
|
||||
|
||||
//int inet_aton(const char *cp, struct in_addr *inp);
|
||||
|
||||
int fcntl (int fd, int flag1, ...);
|
||||
|
||||
size_t recvmsg ( SOCKET s, struct msghdr *msg, int flags );
|
||||
size_t sendmsg ( SOCKET s, const struct msghdr *msg, int flags );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _WINPORTING_H_
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef INC__WINDOWS_SYSLOG_DEFS_H
|
||||
#define INC__WINDOWS_SYSLOG_DEFS_H
|
||||
#ifndef INC_SRT_WINDOWS_SYSLOG_DEFS_H
|
||||
#define INC_SRT_WINDOWS_SYSLOG_DEFS_H
|
||||
|
||||
#define LOG_EMERG 0
|
||||
#define LOG_ALERT 1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef INC__WIN_WINTIME
|
||||
#define INC__WIN_WINTIME
|
||||
#ifndef INC_SRT_WIN_WINTIME
|
||||
#define INC_SRT_WIN_WINTIME
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
@ -7,7 +7,6 @@
|
|||
// where pthread.h, which defines _POSIX_THREAD_SAFE_FUNCTIONS,
|
||||
// has to be included before time.h so that time.h defines
|
||||
// localtime_r correctly
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -53,4 +52,4 @@ SRTCOMPAT_WINTIME_STATIC_INLINE_DECL int gettimeofday(
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // INC__WIN_WINTIME
|
||||
#endif // INC_SRT_WIN_WINTIME
|
||||
|
|
38
trunk/3rdparty/srt-1-fit/common/win_time.cpp
vendored
38
trunk/3rdparty/srt-1-fit/common/win_time.cpp
vendored
|
@ -27,39 +27,11 @@ void SRTCompat_timeradd(struct timeval *a, struct timeval *b, struct timeval *re
|
|||
}
|
||||
}
|
||||
|
||||
int SRTCompat_gettimeofday(struct timeval* tp, struct timezone* tz)
|
||||
int SRTCompat_gettimeofday(struct timeval* tp, struct timezone*)
|
||||
{
|
||||
static LARGE_INTEGER tickFrequency, epochOffset;
|
||||
|
||||
// For our first call, use "ftime()", so that we get a time with a proper epoch.
|
||||
// For subsequent calls, use "QueryPerformanceCount()", because it's more fine-grain.
|
||||
static int isFirstCall = 1;
|
||||
|
||||
LARGE_INTEGER tickNow;
|
||||
QueryPerformanceCounter(&tickNow);
|
||||
|
||||
if (isFirstCall)
|
||||
{
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
tp->tv_sec = (long)tb.time;
|
||||
tp->tv_usec = 1000*tb.millitm;
|
||||
|
||||
// Also get our counter frequency:
|
||||
QueryPerformanceFrequency(&tickFrequency);
|
||||
|
||||
// And compute an offset to add to subsequent counter times, so we get a proper epoch:
|
||||
epochOffset.QuadPart = tb.time*tickFrequency.QuadPart + (tb.millitm*tickFrequency.QuadPart)/1000 - tickNow.QuadPart;
|
||||
|
||||
isFirstCall = 0; // for next time
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust our counter time so that we get a proper epoch:
|
||||
tickNow.QuadPart += epochOffset.QuadPart;
|
||||
|
||||
tp->tv_sec = (long) (tickNow.QuadPart / tickFrequency.QuadPart);
|
||||
tp->tv_usec = (long) (((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);
|
||||
}
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
tp->tv_sec = (long)tb.time;
|
||||
tp->tv_usec = 1000*tb.millitm;
|
||||
return 0;
|
||||
}
|
||||
|
|
25
trunk/3rdparty/srt-1-fit/configure
vendored
25
trunk/3rdparty/srt-1-fit/configure
vendored
|
@ -102,7 +102,7 @@ foreach {o desc} $options {
|
|||
}
|
||||
|
||||
|
||||
if { $argv == "--help" } {
|
||||
if { $argv == "--help" || $argv == "-h" } {
|
||||
puts stderr "Usage: ./configure \[options\]"
|
||||
puts stderr "OPTIONS:"
|
||||
foreach o [lsort [array names opt]] {
|
||||
|
@ -153,8 +153,10 @@ foreach a $argv {
|
|||
|
||||
set type ""
|
||||
|
||||
if { [string first = $a] != -1 } {
|
||||
lassign [split $a =] a val
|
||||
if { [set a1 [string first = $a]] != -1 } {
|
||||
# Do not split. Options may include =.
|
||||
set val [string range $a $a1+1 end]
|
||||
set a [string range $a 0 $a1-1]
|
||||
}
|
||||
|
||||
if { [dict exists $::alias $a] } {
|
||||
|
@ -194,6 +196,23 @@ if { $saveopt != "" } {
|
|||
error "Extra unhandled argument: $saveopt"
|
||||
}
|
||||
|
||||
# Save the original call into config-status.sh
|
||||
|
||||
set ofd [open config-status.sh w]
|
||||
puts $ofd "#!/bin/bash"
|
||||
puts -nonewline $ofd "$argv0 "
|
||||
foreach a $argv {
|
||||
set len 1
|
||||
if {[catch {llength $a} len] || $len > 1 } {
|
||||
puts -nonewline $ofd "'$a' "
|
||||
} else {
|
||||
puts -nonewline $ofd "$a "
|
||||
}
|
||||
}
|
||||
puts $ofd ""
|
||||
close $ofd
|
||||
file attributes config-status.sh -permissions +x
|
||||
|
||||
set cmakeopt ""
|
||||
|
||||
resolve_disablers
|
||||
|
|
107
trunk/3rdparty/srt-1-fit/configure-data.tcl
vendored
107
trunk/3rdparty/srt-1-fit/configure-data.tcl
vendored
|
@ -25,47 +25,56 @@
|
|||
|
||||
# Options processed here internally, not passed to cmake
|
||||
set internal_options {
|
||||
with-compiler-prefix=<prefix> "set C/C++ toolchains <prefix>gcc and <prefix>g++"
|
||||
with-compiler-type=<name> "compiler type: gcc(default), cc, others simply add ++ for C++"
|
||||
with-srt-name=<name> "Override srt library name"
|
||||
with-haicrypt-name=<name> "Override haicrypt library name (if compiled separately)"
|
||||
with-compiler-prefix=<prefix> "set C/C++ toolchains <prefix>gcc and <prefix>g++"
|
||||
with-compiler-type=<name> "compiler type: gcc(default), cc, others simply add ++ for C++"
|
||||
with-srt-name=<name> "Override srt library name"
|
||||
with-haicrypt-name=<name> "Override haicrypt library name (if compiled separately)"
|
||||
with-atomic=<spec> "Select implementation for atomics (compiler-intrinsics or sync-mutex)"
|
||||
}
|
||||
|
||||
# Options that refer directly to variables used in CMakeLists.txt
|
||||
set cmake_options {
|
||||
cygwin-use-posix "Should the POSIX API be used for cygwin. Ignored if the system isn't cygwin. (default: OFF)"
|
||||
enable-encryption "Should encryption features be enabled (default: ON)"
|
||||
enable-c++11 "Should the c++11 parts (srt-live-transmit) be enabled (default: ON)"
|
||||
enable-c++11 "Should the c++11 parts (srt-live-transmit) be enabled (default: ON, with gcc < 4.7 OFF)"
|
||||
enable-apps "Should the Support Applications be Built? (default: ON)"
|
||||
enable-bonding "Enable 'bonding' SRT feature (default: OFF)"
|
||||
enable-testing "Should developer testing applications be built (default: OFF)"
|
||||
enable-c++-deps "Extra library dependencies in srt.pc for C language (default: OFF)"
|
||||
enable-heavy-logging "Should heavy debug logging be enabled (default: OFF)"
|
||||
enable-profile "Should instrument the code for profiling. Ignored for non-GNU compiler. (default: OFF)"
|
||||
enable-logging "Should logging be enabled (default: ON)"
|
||||
enable-debug=<0,1,2> "Enable debug mode (0=disabled, 1=debug, 2=rel-with-debug)"
|
||||
enable-heavy-logging "Should heavy debug logging be enabled (default: OFF)"
|
||||
enable-haicrypt-logging "Should logging in haicrypt be enabled (default: OFF)"
|
||||
enable-pktinfo "Should pktinfo reading and using be enabled (POSIX only) (default: OFF)"
|
||||
enable-shared "Should libsrt be built as a shared library (default: ON)"
|
||||
enable-static "Should libsrt be built as a static library (default: ON)"
|
||||
enable-relative-libpath "Should applications contain relative library paths, like ../lib (default: OFF)"
|
||||
enable-getnameinfo "In-logs sockaddr-to-string should do rev-dns (default: OFF)"
|
||||
enable-unittests "Enable Unit Tests (will download Google UT) (default: OFF)"
|
||||
enable-encryption "Should encryption features be enabled (default: ON)"
|
||||
enable-c++-deps "Extra library dependencies in srt.pc for C language (default: ON)"
|
||||
use-static-libstdc++ "Should use static rather than shared libstdc++ (default: OFF)"
|
||||
enable-inet-pton "Set to OFF to prevent usage of inet_pton when building against modern SDKs (default: ON)"
|
||||
enable-code-coverage "Enable code coverage reporting (default: OFF)"
|
||||
enable-monotonic-clock "Enforced clock_gettime with monotonic clock on GC CV /temporary fix for #729/ (default: OFF)"
|
||||
enable-profile "Should instrument the code for profiling. Ignored for non-GNU compiler. (default: OFF)"
|
||||
enable-relative-libpath "Should applications contain relative library paths, like ../lib (default: OFF)"
|
||||
enable-shared "Should libsrt be built as a shared library (default: ON)"
|
||||
enable-static "Should libsrt be built as a static library (default: ON)"
|
||||
enable-suflip "Should suflip tool be built (default: OFF)"
|
||||
enable-getnameinfo "In-logs sockaddr-to-string should do rev-dns (default: OFF)"
|
||||
enable-unittests "Enable unit tests (default: OFF)"
|
||||
enable-thread-check "Enable #include <threadcheck.h> that implements THREAD_* macros"
|
||||
openssl-crypto-library=<filepath> "Path to a library."
|
||||
openssl-include-dir=<path> "Path to a file."
|
||||
openssl-ssl-library=<filepath> "Path to a library."
|
||||
pkg-config-executable=<filepath> "pkg-config executable"
|
||||
pthread-include-dir=<path> "Path to a file."
|
||||
pthread-library=<filepath> "Path to a library."
|
||||
enable-stdc++-sync "Use standard C++11 chrono/threads instead of pthread wrapper (default: OFF, on Windows: ON)"
|
||||
use-openssl-pc "Use pkg-config to find OpenSSL libraries (default: ON)"
|
||||
openssl-use-static-libs "Link OpenSSL statically (default: OFF)."
|
||||
use-busy-waiting "Enable more accurate sending times at a cost of potentially higher CPU load (default: OFF)"
|
||||
use-gnustl "Get c++ library/headers from the gnustl.pc"
|
||||
enable-sock-cloexec "Enable setting SOCK_CLOEXEC on a socket (default: ON)"
|
||||
enable-show-project-config "Enables use of ShowProjectConfig() in cmake (default: OFF)"
|
||||
enable-new-rcvbuffer "Enables the new receiver buffer implementation (default: ON)"
|
||||
enable-clang-tsa "Enable Clang's Thread-Safety-Analysis (default: OFF)"
|
||||
atomic-use-srt-sync-mutex "Use mutex to implement atomics (alias: --with-atomic=sync-mutex) (default: OFF)"
|
||||
|
||||
use-enclib "Encryption library to be used: openssl(default), gnutls, mbedtls"
|
||||
use-gnutls "DEPRECATED. Use USE_ENCLIB=openssl|gnutls|mbedtls instead"
|
||||
use-openssl-pc "Use pkg-config to find OpenSSL libraries (default: ON)"
|
||||
use-static-libstdc++ "Should use static rather than shared libstdc++ (default: OFF)"
|
||||
enable-debug=<0,1,2> "Enable debug mode (0=disabled, 1=debug, 2=rel-with-debug)"
|
||||
pkg-config-executable=<filepath> "pkg-config executable"
|
||||
openssl-crypto-library=<filepath> "OpenSSL: Path to a libcrypto library."
|
||||
openssl-include-dir=<path> "OpenSSL: Path to includes."
|
||||
openssl-ssl-library=<filepath> "OpenSSL: Path to a libssl library."
|
||||
pthread-include-dir=<path> "PThread: Path to includes"
|
||||
pthread-library=<filepath> "PThread: Path to the pthread library."
|
||||
}
|
||||
|
||||
set options $internal_options$cmake_options
|
||||
|
@ -162,6 +171,24 @@ proc preprocess {} {
|
|||
set ::haicrypt_name $::optval(--with-haicrypt-name)
|
||||
unset ::optval(--with-haicrypt-name)
|
||||
}
|
||||
|
||||
if { "--with-atomic" in $::optkeys } {
|
||||
switch -- $::optval(--with-atomic) {
|
||||
compiler-intrinsics {
|
||||
}
|
||||
|
||||
sync-mutex {
|
||||
set ::optval(--atomic-use-srt-sync-mutex) 1
|
||||
}
|
||||
|
||||
default {
|
||||
puts "ERROR: --with-atomic option accepts two values: compiler-intrinsics (default) or sync-mutex"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
unset ::optval(--with-atomic)
|
||||
}
|
||||
}
|
||||
|
||||
proc GetCompilerCommand {} {
|
||||
|
@ -170,9 +197,16 @@ proc GetCompilerCommand {} {
|
|||
# --cmake-c[++]-compiler
|
||||
# (cmake-toolchain-file will set things up without the need to check things here)
|
||||
|
||||
set compiler gcc
|
||||
if { [info exists ::optval(--with-compiler-type)] } {
|
||||
set compiler $::optval(--with-compiler-type)
|
||||
}
|
||||
|
||||
if { [info exists ::optval(--with-compiler-prefix)] } {
|
||||
set prefix $::optval(--with-compiler-prefix)
|
||||
return ${prefix}gcc
|
||||
return ${prefix}$compiler
|
||||
} else {
|
||||
return $compiler
|
||||
}
|
||||
|
||||
if { [info exists ::optval(--cmake-c-compiler)] } {
|
||||
|
@ -201,6 +235,7 @@ proc postprocess {} {
|
|||
set toolchain_changed no
|
||||
foreach changer {
|
||||
--with-compiler-prefix
|
||||
--with-compiler-type
|
||||
--cmake-c-compiler
|
||||
--cmake-c++-compiler
|
||||
--cmake-cxx-compiler
|
||||
|
@ -223,6 +258,7 @@ proc postprocess {} {
|
|||
# Check characteristics of the compiler - in particular, whether the target is different
|
||||
# than the current target.
|
||||
set compiler_path ""
|
||||
set target_platform ""
|
||||
set cmd [GetCompilerCommand]
|
||||
if { $cmd != "" } {
|
||||
set gcc_version [exec $cmd -v 2>@1]
|
||||
|
@ -237,7 +273,7 @@ proc postprocess {} {
|
|||
}
|
||||
|
||||
if { $target_platform == "" } {
|
||||
puts "NOTE: can't obtain target from gcc -v: $l"
|
||||
puts "NOTE: can't obtain target from '[file tail $cmd] -v': $l - ASSUMING HOST compiler"
|
||||
} else {
|
||||
if { $target_platform != $::tcl_platform(machine) } {
|
||||
puts "NOTE: foreign target type detected ($target)" ;# - setting CROSSCOMPILING flag"
|
||||
|
@ -245,6 +281,8 @@ proc postprocess {} {
|
|||
set iscross 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
puts "CONFIGURE: default compiler used"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,8 +370,19 @@ proc postprocess {} {
|
|||
# Otherwise don't set PKG_CONFIG_PATH and we'll see.
|
||||
}
|
||||
|
||||
if { $::HAVE_DARWIN && !$toolchain_changed} {
|
||||
|
||||
set use_brew 0
|
||||
if { $::HAVE_DARWIN && !$toolchain_changed } {
|
||||
set use_brew 1
|
||||
}
|
||||
if { $use_brew } {
|
||||
foreach item $::cmakeopt {
|
||||
if { [string first "Android" $item] != -1 } {
|
||||
set use_brew 0
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if { $use_brew } {
|
||||
if { $have_gnutls } {
|
||||
# Use gnutls explicitly, as found in brew
|
||||
set er [catch {exec brew info gnutls} res]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef INC__CRYSPR_CONFIG_H
|
||||
#define INC__CRYSPR_CONFIG_H
|
||||
#ifndef INC_SRT_CRYSPR_CONFIG_H
|
||||
#define INC_SRT_CRYSPR_CONFIG_H
|
||||
|
||||
// Size of the single block for encryption.
|
||||
// This might need tweaking for particular implementation library.
|
||||
|
@ -8,14 +8,22 @@
|
|||
#if defined(USE_OPENSSL)
|
||||
#include "cryspr-openssl.h"
|
||||
#define cryspr4SRT() crysprOpenSSL()
|
||||
#define CRYSPR_IMPL_DESC "OpenSSL-AES"
|
||||
#elif defined(USE_OPENSSL_EVP)
|
||||
#include "cryspr-openssl-evp.h"
|
||||
#define cryspr4SRT() crysprOpenSSL_EVP()
|
||||
#define CRYSPR_IMPL_DESC "OpenSSL-EVP"
|
||||
#elif defined(USE_GNUTLS)
|
||||
#include "cryspr-gnutls.h"
|
||||
#define cryspr4SRT() crysprGnuTLS()
|
||||
#define CRYSPR_IMPL_DESC "GnuTLS"
|
||||
#elif defined(USE_MBEDTLS)
|
||||
#include "cryspr-mbedtls.h"
|
||||
#define cryspr4SRT() crysprMbedtls()
|
||||
#define CRYSPR_IMPL_DESC "MbedTLS"
|
||||
#else
|
||||
#error Cryspr implementation not selected. Please define USE_* + OPENSSL/GNUTLS/MBEDTLS.
|
||||
#define CRYSPR_IMPL_DESC "No Cipher"
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
written by
|
||||
Haivision Systems Inc.
|
||||
|
||||
2022-05-19 (jdube)
|
||||
CRYSPR2 adaptation
|
||||
2019-06-27 (jdube)
|
||||
GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT)
|
||||
*****************************************************************************/
|
||||
|
@ -24,6 +26,10 @@ written by
|
|||
typedef struct tag_crysprGnuTLS_AES_cb {
|
||||
CRYSPR_cb ccb; /* CRYSPR control block */
|
||||
/* Add other cryptolib specific data here */
|
||||
#ifdef CRYSPR2
|
||||
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#endif
|
||||
} crysprGnuTLS_cb;
|
||||
|
||||
|
||||
|
@ -33,11 +39,14 @@ int crysprGnuTLS_Prng(unsigned char *rn, int len)
|
|||
}
|
||||
|
||||
int crysprGnuTLS_AES_SetKey(
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
|
||||
bool bEncrypt, /* true:encrypt key, false:decrypt key*/
|
||||
const unsigned char *kstr, /* key string */
|
||||
size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
|
||||
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
|
||||
{
|
||||
(void)cipher_type;
|
||||
|
||||
if (bEncrypt) { /* Encrypt key */
|
||||
if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n");
|
||||
|
@ -114,6 +123,31 @@ int crysprGnuTLS_AES_CtrCipher( /* AES-CTR128 Encryption */
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CRYSPR2
|
||||
static CRYSPR_cb *crysprGnuTLS_Open(CRYSPR_methods *cryspr, size_t max_len)
|
||||
{
|
||||
crysprGnuTLS_cb *aes_data;
|
||||
CRYSPR_cb *cryspr_cb;
|
||||
|
||||
aes_data = (crysprGnuTLS_cb *)crysprHelper_Open(cryspr, sizeof(crysprGnuTLS_cb), max_len);
|
||||
if (NULL == aes_data) {
|
||||
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprGnuTLS_cb), max_len);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
|
||||
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
|
||||
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
|
||||
|
||||
return(&aes_data->ccb);
|
||||
}
|
||||
|
||||
static int crysprGnuTLS_Close(CRYSPR_cb *cryspr_cb)
|
||||
{
|
||||
return(crysprHelper_Close(cryspr_cb));
|
||||
}
|
||||
#endif /* CRYSPR2 */
|
||||
|
||||
#ifdef CRYSPR_HAS_PBKDF2
|
||||
/*
|
||||
* Password-based Key Derivation Function
|
||||
|
@ -157,8 +191,13 @@ CRYSPR_methods *crysprGnuTLS(void)
|
|||
#endif
|
||||
|
||||
//--Crypto Session (Top API)
|
||||
#ifdef CRYSPR2
|
||||
crysprGnuTLS_methods.open = crysprGnuTLS_Open;
|
||||
crysprGnuTLS_methods.close = crysprGnuTLS_Close;
|
||||
#else /* CRYSPR2 */
|
||||
// crysprGnuTLS_methods.open =
|
||||
// crysprGnuTLS_methods.close =
|
||||
#endif /* CRYSPR2 */
|
||||
//--Keying material (km) encryption
|
||||
#if CRYSPR_HAS_PBKDF2
|
||||
crysprGnuTLS_methods.km_pbkdf2 = crysprGnuTLS_KmPbkdf2;
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
written by
|
||||
Haivision Systems Inc.
|
||||
|
||||
2022-05-19 (jdube)
|
||||
CRYSPR2 adaptation
|
||||
2019-06-27 (jdube)
|
||||
GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT)
|
||||
MBedTLS CRYSPR/4SRT (CRYypto Service PRovider for SRT)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hcrypt.h"
|
||||
|
@ -29,11 +31,14 @@ written by
|
|||
// Static members of cryspr::mbedtls class.
|
||||
static mbedtls_ctr_drbg_context crysprMbedtls_ctr_drbg;
|
||||
static mbedtls_entropy_context crysprMbedtls_entropy;
|
||||
static mbedtls_md_context_t crysprMbedtls_mdctx;
|
||||
|
||||
typedef struct tag_crysprGnuTLS_AES_cb {
|
||||
typedef struct tag_crysprMBedTLS_AES_cb {
|
||||
CRYSPR_cb ccb; /* CRYSPR control block */
|
||||
/* Add other cryptolib specific data here */
|
||||
#ifdef CRYSPR2
|
||||
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#endif
|
||||
} crysprMbedtls_cb;
|
||||
|
||||
|
||||
|
@ -49,25 +54,30 @@ int crysprMbedtls_Prng(unsigned char *rn, int len)
|
|||
}
|
||||
|
||||
int crysprMbedtls_AES_SetKey(
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
|
||||
bool bEncrypt, /* true:encrypt key, false:decrypt key*/
|
||||
const unsigned char *kstr, /* key string */
|
||||
size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes, for AES128,AES192, or AES256) */
|
||||
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
|
||||
{
|
||||
(void)cipher_type;
|
||||
|
||||
if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
#ifdef CRYSPR2
|
||||
(void)cipher_type;
|
||||
#endif
|
||||
// mbedtls uses the "bits" convention (128, 192, 254), just like openssl.
|
||||
// kstr_len is in "bytes" convention (16, 24, 32).
|
||||
|
||||
if (bEncrypt) { /* Encrypt key */
|
||||
ret = mbedtls_aes_setkey_enc(aes_key, kstr, kstr_len*8);
|
||||
ret = mbedtls_aes_setkey_enc(aes_key, kstr, (unsigned int)kstr_len*8);
|
||||
} else { /* Decrypt key */
|
||||
ret = mbedtls_aes_setkey_dec(aes_key, kstr, kstr_len*8);
|
||||
ret = mbedtls_aes_setkey_dec(aes_key, kstr, (unsigned int)kstr_len*8);
|
||||
}
|
||||
|
||||
return ret == 0 ? 0 : -1;
|
||||
|
@ -81,8 +91,8 @@ int crysprMbedtls_AES_EcbCipher( /* AES Electronic Codebook cipher*/
|
|||
unsigned char *out_txt, /* dst (cipher text) */
|
||||
size_t *outlen) /* dst len */
|
||||
{
|
||||
int nblk = inlen/CRYSPR_AESBLKSZ;
|
||||
int nmore = inlen%CRYSPR_AESBLKSZ;
|
||||
int nblk = (int)(inlen/CRYSPR_AESBLKSZ);
|
||||
int nmore = (int)(inlen%CRYSPR_AESBLKSZ);
|
||||
int i;
|
||||
|
||||
if (bEncrypt) {
|
||||
|
@ -146,6 +156,30 @@ int crysprMbedtls_AES_CtrCipher( /* AES-CTR128 Encryption */
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CRYSPR2
|
||||
static CRYSPR_cb *crysprMbedtls_Open(CRYSPR_methods *cryspr, size_t max_len)
|
||||
{
|
||||
crysprMbedtls_cb *aes_data;
|
||||
|
||||
aes_data = (crysprMbedtls_cb *)crysprHelper_Open(cryspr, sizeof(crysprMbedtls_cb), max_len);
|
||||
if (NULL == aes_data) {
|
||||
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprMbedtls_cb), max_len);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
|
||||
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
|
||||
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
|
||||
|
||||
return(&aes_data->ccb);
|
||||
}
|
||||
|
||||
static int crysprMbedtls_Close(CRYSPR_cb *cryspr_cb)
|
||||
{
|
||||
return(crysprHelper_Close(cryspr_cb));
|
||||
}
|
||||
#endif /* CRYSPR2 */
|
||||
|
||||
/*
|
||||
* Password-based Key Derivation Function
|
||||
*/
|
||||
|
@ -161,9 +195,29 @@ int crysprMbedtls_KmPbkdf2(
|
|||
{
|
||||
(void)cryspr_cb;
|
||||
|
||||
int ret = mbedtls_pkcs5_pbkdf2_hmac(&crysprMbedtls_mdctx,
|
||||
const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||
if ( ifo == NULL ) {
|
||||
// XXX report error, log?
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_md_context_t mdctx;
|
||||
mbedtls_md_init(&mdctx);
|
||||
|
||||
const int yes_use_hmac = 1;
|
||||
int ret;
|
||||
if ( (ret = mbedtls_md_setup(&mdctx, ifo, yes_use_hmac)) != 0 ) {
|
||||
mbedtls_md_free(&mdctx);
|
||||
|
||||
// XXX report error, log?
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mbedtls_pkcs5_pbkdf2_hmac(&mdctx,
|
||||
(unsigned char*)passwd, passwd_len, salt, salt_len,
|
||||
itr, key_len, out);
|
||||
itr, (uint32_t)key_len, out);
|
||||
|
||||
mbedtls_md_free(&mdctx);
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
@ -196,8 +250,13 @@ CRYSPR_methods *crysprMbedtls(void)
|
|||
#endif
|
||||
|
||||
//--Crypto Session (Top API)
|
||||
#ifdef CRYSPR2
|
||||
crysprMbedtls_methods.open = crysprMbedtls_Open;
|
||||
crysprMbedtls_methods.close = crysprMbedtls_Close;
|
||||
#else
|
||||
// crysprMbedtls_methods.open =
|
||||
// crysprMbedtls_methods.close =
|
||||
#endif
|
||||
//--Keying material (km) encryption
|
||||
crysprMbedtls_methods.km_pbkdf2 = crysprMbedtls_KmPbkdf2;
|
||||
// crysprMbedtls_methods.km_setkey =
|
||||
|
@ -220,14 +279,6 @@ CRYSPR_methods *crysprMbedtls(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Ok, mbedtls with all flexibility you couldn't make it more complicated.
|
||||
|
||||
mbedtls_md_init(&crysprMbedtls_mdctx);
|
||||
const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||
const int yes_use_hmac = 1;
|
||||
mbedtls_md_setup(&crysprMbedtls_mdctx, ifo, yes_use_hmac);
|
||||
|
||||
|
||||
return(&crysprMbedtls_methods);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ written by
|
|||
Haivision Systems Inc.
|
||||
|
||||
2019-06-27 (jdube)
|
||||
GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT)
|
||||
MBedTLS CRYSPR/4SRT (CRYypto Service PRovider for SRT)
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef CRYSPR_GNUTLS_H
|
||||
#define CRYSPR_GNUTLS_H
|
||||
#ifndef CRYSPR_MBEDTLS_H
|
||||
#define CRYSPR_MBEDTLS_H
|
||||
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/aes.h>
|
||||
|
@ -52,12 +52,12 @@ written by
|
|||
/*
|
||||
#define CRYSPR_AESCTX to the CRYSPR specifix AES key context object.
|
||||
This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK
|
||||
It is set from hte keystring through CRYSPR_methods.aes_set_key and passed
|
||||
It is set from the keystring through CRYSPR_methods.aes_set_key and passed
|
||||
to CRYSPR_methods.aes_XXX.
|
||||
*/
|
||||
typedef struct mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
|
||||
typedef mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
|
||||
|
||||
struct tag_CRYSPR_methods *crysprMbedtls(void);
|
||||
|
||||
#endif /* CRYSPR_GNUTLS_H */
|
||||
#endif /* CRYSPR_MBEDTLS_H */
|
||||
|
||||
|
|
417
trunk/3rdparty/srt-1-fit/haicrypt/cryspr-openssl-evp.c
vendored
Normal file
417
trunk/3rdparty/srt-1-fit/haicrypt/cryspr-openssl-evp.c
vendored
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Haivision Systems Inc.
|
||||
|
||||
2022-05-19 (jdube)
|
||||
OpenSSL EVP CRYSPR/4SRT (CRYypto Service PRovider for SRT).
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hcrypt.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct tag_crysprOpenSSL_EVP_cb
|
||||
{
|
||||
CRYSPR_cb ccb;
|
||||
/* Add cryptolib specific data here */
|
||||
} crysprOpenSSL_EVP_cb;
|
||||
|
||||
int crysprOpenSSL_EVP_Prng(unsigned char* rn, int len)
|
||||
{
|
||||
return (RAND_bytes(rn, len) <= 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
const EVP_CIPHER* (*Xcipher_fnptr)(void) = EVP_aes_128_ecb;
|
||||
|
||||
const EVP_CIPHER* (*_crysprOpenSSL_EVP_cipher_fnptr[][3])(void) = {
|
||||
{NULL, NULL, NULL}, // HCRYPT_CTX_MODE_CLRTXT
|
||||
{EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb}, // HCRYPT_CTX_MODE_AESECB
|
||||
{EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr}, // HCRYPT_CTX_MODE_AESCTR
|
||||
{NULL, NULL, NULL}, // HCRYPT_CTX_MODE_AESCBC
|
||||
{EVP_aes_128_gcm, EVP_aes_192_gcm, EVP_aes_256_gcm}, // HCRYPT_CTX_MODE_AESGCM
|
||||
};
|
||||
|
||||
int crysprOpenSSL_EVP_AES_SetKey(
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
|
||||
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
|
||||
const unsigned char* kstr, /* key sttring*/
|
||||
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128, AES192, or AES256) */
|
||||
CRYSPR_AESCTX* aes_key) /* CRYpto Service PRovider AES Key context */
|
||||
{
|
||||
const EVP_CIPHER* cipher = NULL;
|
||||
int idxKlen = (int)((kstr_len / 8) - 2); /* key_len index in cipher_fnptr array in [0,1,2] range */
|
||||
|
||||
switch (cipher_type)
|
||||
{
|
||||
case HCRYPT_CTX_MODE_CLRTXT:
|
||||
return 0;
|
||||
case HCRYPT_CTX_MODE_AESECB:
|
||||
break;
|
||||
case HCRYPT_CTX_MODE_AESCTR:
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
/* internal implementation of AES-CTR using crypto lib's AES-ECB */
|
||||
cipher_type = HCRYPT_CTX_MODE_AESECB;
|
||||
#endif
|
||||
break;
|
||||
case HCRYPT_CTX_MODE_AESGCM:
|
||||
break;
|
||||
default:
|
||||
HCRYPT_LOG(LOG_ERR,
|
||||
"invalid cipher type (%d). Expected: [%d..%d]\n",
|
||||
cipher_type,
|
||||
HCRYPT_CTX_MODE_AESECB,
|
||||
HCRYPT_CTX_MODE_AESCTR);
|
||||
return (-1);
|
||||
}
|
||||
switch (kstr_len)
|
||||
{
|
||||
case 128 / 8:
|
||||
case 192 / 8:
|
||||
case 256 / 8:
|
||||
break;
|
||||
default:
|
||||
HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)kstr_len);
|
||||
return -1;
|
||||
}
|
||||
cipher = _crysprOpenSSL_EVP_cipher_fnptr[cipher_type][idxKlen]();
|
||||
|
||||
if (bEncrypt)
|
||||
{ /* Encrypt key */
|
||||
if (!EVP_EncryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Decrypt key */
|
||||
if (!EVP_DecryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static CRYSPR_cb* crysprOpenSSL_EVP_Open(CRYSPR_methods* cryspr, size_t max_len)
|
||||
{
|
||||
CRYSPR_cb* cryspr_cb = crysprHelper_Open(cryspr, sizeof(*cryspr_cb), max_len);
|
||||
if (NULL == cryspr_cb)
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "crysprFallback_Open(%p, %zd) failed\n", cryspr, max_len);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cryspr_cb->aes_kek = EVP_CIPHER_CTX_new();
|
||||
|
||||
cryspr_cb->aes_sek[0] = EVP_CIPHER_CTX_new();
|
||||
|
||||
cryspr_cb->aes_sek[1] = EVP_CIPHER_CTX_new();
|
||||
|
||||
return (cryspr_cb);
|
||||
}
|
||||
|
||||
static int crysprOpenSSL_EVP_Close(CRYSPR_cb* cryspr_cb)
|
||||
{
|
||||
if (NULL != cryspr_cb)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[0]);
|
||||
EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[1]);
|
||||
EVP_CIPHER_CTX_free(cryspr_cb->aes_kek);
|
||||
}
|
||||
return (crysprHelper_Close(cryspr_cb));
|
||||
}
|
||||
|
||||
#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
|
||||
|
||||
int crysprOpenSSL_EVP_AES_EcbCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
|
||||
const unsigned char* indata, /* src (clear text if encrypt, cipher text otherwise)*/
|
||||
size_t inlen, /* indata length */
|
||||
unsigned char* out_txt, /* dst (cipher text if encrypt, clear text otherwise) */
|
||||
size_t* outlen_p) /* in/out dst len */
|
||||
{
|
||||
int nmore = inlen % CRYSPR_AESBLKSZ; /* bytes in last incomplete block */
|
||||
int nblk = (int)(inlen / CRYSPR_AESBLKSZ + (nmore ? 1 : 0)); /* blocks including incomplete */
|
||||
size_t outsiz = (outlen_p ? *outlen_p : 0);
|
||||
int c_len = 0, f_len = 0;
|
||||
|
||||
(void)bEncrypt; // not needed, alreadydefined in context
|
||||
|
||||
if (outsiz % CRYSPR_AESBLKSZ)
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
|
||||
return (-1); /* output buf size must be a multiple of AES block size (16) */
|
||||
}
|
||||
if ((outsiz > 16) && ((int)outsiz < (nblk * CRYSPR_AESBLKSZ)))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
|
||||
return (-1); /* output buf size must have room for PKCS7 padding */
|
||||
}
|
||||
/* allows reusing of 'e' for multiple encryption cycles */
|
||||
if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, NULL, bEncrypt))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "EVP_CipherInit_ex(%p,NULL,...,-1) failed\n", aes_key);
|
||||
return -1;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding(%p) failed", aes_key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext, c_len is filled with the length of ciphertext generated,
|
||||
* cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
|
||||
*/
|
||||
if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int)inlen))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "EVP_CipherUpdate(%p, out, %d, in, %d) failed\n", aes_key, c_len, inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext with the final remaining bytes */
|
||||
/* Useless with pre-padding */
|
||||
f_len = 0;
|
||||
if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
|
||||
{
|
||||
#if ENABLE_HAICRYPT_LOGGING
|
||||
char szErrBuf[256];
|
||||
HCRYPT_LOG(LOG_ERR,
|
||||
"EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
|
||||
c_len,
|
||||
f_len,
|
||||
ERR_error_string(ERR_get_error(), szErrBuf));
|
||||
#endif /*ENABLE_HAICRYPT_LOGGING*/
|
||||
return -1;
|
||||
}
|
||||
if (outlen_p != NULL) *outlen_p = nblk * CRYSPR_AESBLKSZ;
|
||||
return 0;
|
||||
}
|
||||
#endif /* !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) */
|
||||
|
||||
int crysprOpenSSL_EVP_AES_CtrCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
|
||||
unsigned char* iv, /* iv */
|
||||
const unsigned char* indata, /* src */
|
||||
size_t inlen, /* length */
|
||||
unsigned char* out_txt) /* dest */
|
||||
|
||||
{
|
||||
int c_len, f_len;
|
||||
|
||||
(void)bEncrypt;
|
||||
|
||||
/* allows reusing of 'e' for multiple encryption cycles */
|
||||
if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed");
|
||||
return -1;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext, c_len is filled with the length of ciphertext generated,
|
||||
* cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
|
||||
*/
|
||||
if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int)inlen))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext with the final remaining bytes */
|
||||
/* Useless with pre-padding */
|
||||
f_len = 0;
|
||||
if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
|
||||
{
|
||||
#if ENABLE_HAICRYPT_LOGGING
|
||||
char szErrBuf[256];
|
||||
HCRYPT_LOG(LOG_ERR,
|
||||
"EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
|
||||
c_len,
|
||||
f_len,
|
||||
ERR_error_string(ERR_get_error(), szErrBuf));
|
||||
#endif /*ENABLE_HAICRYPT_LOGGING*/
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crysprOpenSSL_EVP_AES_GCMCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
|
||||
unsigned char* iv, /* iv */
|
||||
const unsigned char* aad, /* associated data */
|
||||
size_t aadlen,
|
||||
const unsigned char* indata, /* src */
|
||||
size_t inlen, /* length */
|
||||
unsigned char* out_txt,
|
||||
unsigned char* out_tag) /* auth tag */
|
||||
{
|
||||
int c_len, f_len;
|
||||
|
||||
/* allows reusing of 'e' for multiple encryption cycles */
|
||||
if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed");
|
||||
return -1;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide any AAD data. This can be called zero or more times as
|
||||
* required
|
||||
*/
|
||||
if (1 != EVP_CipherUpdate(aes_key, NULL, &c_len, aad, (int) aadlen))
|
||||
{
|
||||
ERR_print_errors_fp(stderr);
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_EncryptUpdate failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext, c_len is filled with the length of ciphertext generated,
|
||||
* cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
|
||||
*/
|
||||
if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int) inlen))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!bEncrypt && !EVP_CIPHER_CTX_ctrl(aes_key, EVP_CTRL_GCM_SET_TAG, HAICRYPT_AUTHTAG_MAX, out_tag)) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_EncryptUpdate failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update ciphertext with the final remaining bytes */
|
||||
/* Useless with pre-padding */
|
||||
f_len = 0;
|
||||
if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
|
||||
{
|
||||
#if ENABLE_HAICRYPT_LOGGING
|
||||
char szErrBuf[256];
|
||||
HCRYPT_LOG(LOG_ERR,
|
||||
"EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
|
||||
c_len,
|
||||
f_len,
|
||||
ERR_error_string(ERR_get_error(), szErrBuf));
|
||||
#endif /*ENABLE_HAICRYPT_LOGGING*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the tag if we are encrypting */
|
||||
if (bEncrypt && !EVP_CIPHER_CTX_ctrl(aes_key, EVP_CTRL_GCM_GET_TAG, HAICRYPT_AUTHTAG_MAX, out_tag))
|
||||
{
|
||||
ERR_print_errors_fp(stderr);
|
||||
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Password-based Key Derivation Function
|
||||
*/
|
||||
int crysprOpenSSL_EVP_KmPbkdf2(CRYSPR_cb* cryspr_cb,
|
||||
char* passwd, /* passphrase */
|
||||
size_t passwd_len, /* passphrase len */
|
||||
unsigned char* salt, /* salt */
|
||||
size_t salt_len, /* salt_len */
|
||||
int itr, /* iterations */
|
||||
size_t key_len, /* key_len */
|
||||
unsigned char* out) /* derived key */
|
||||
{
|
||||
(void)cryspr_cb;
|
||||
int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd, (int)passwd_len, salt, (int)salt_len, itr, (int)key_len, out);
|
||||
return (rc == 1 ? 0 : -1);
|
||||
}
|
||||
|
||||
#if CRYSPR_HAS_AESKWRAP
|
||||
int crysprOpenSSL_EVP_KmWrap(CRYSPR_cb* cryspr_cb, unsigned char* wrap, const unsigned char* sek, unsigned int seklen)
|
||||
{
|
||||
crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
|
||||
EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
|
||||
|
||||
return (((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
|
||||
}
|
||||
|
||||
int crysprOpenSSL_EVP_KmUnwrap(CRYSPR_cb* cryspr_cb,
|
||||
unsigned char* sek, // Stream encrypting key
|
||||
const unsigned char* wrap,
|
||||
unsigned int wraplen)
|
||||
{
|
||||
crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
|
||||
EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
|
||||
|
||||
return (((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0
|
||||
: -1);
|
||||
}
|
||||
#endif /*CRYSPR_HAS_AESKWRAP*/
|
||||
|
||||
static CRYSPR_methods crysprOpenSSL_EVP_methods;
|
||||
|
||||
CRYSPR_methods* crysprOpenSSL_EVP(void)
|
||||
{
|
||||
if (NULL == crysprOpenSSL_EVP_methods.open)
|
||||
{
|
||||
crysprInit(&crysprOpenSSL_EVP_methods); // Default/fallback methods
|
||||
|
||||
crysprOpenSSL_EVP_methods.prng = crysprOpenSSL_EVP_Prng;
|
||||
//--CryptoLib Primitive API-----------------------------------------------
|
||||
crysprOpenSSL_EVP_methods.aes_set_key = crysprOpenSSL_EVP_AES_SetKey;
|
||||
#if CRYSPR_HAS_AESCTR
|
||||
crysprOpenSSL_EVP_methods.aes_ctr_cipher = crysprOpenSSL_EVP_AES_CtrCipher;
|
||||
#endif
|
||||
crysprOpenSSL_EVP_methods.aes_gcm_cipher = crysprOpenSSL_EVP_AES_GCMCipher;
|
||||
#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
|
||||
/* AES-ECB only required if cryspr has no AES-CTR and no AES KeyWrap */
|
||||
/* OpenSSL has both AESCTR and AESKWRP and the AESECB wrapper is only used
|
||||
to test the falback methods */
|
||||
crysprOpenSSL_EVP_methods.aes_ecb_cipher = crysprOpenSSL_EVP_AES_EcbCipher;
|
||||
#endif
|
||||
#if !CRYSPR_HAS_PBKDF2
|
||||
crysprOpenSSL_EVP_methods.sha1_msg_digest = NULL; // Required to use eventual default/fallback KmPbkdf2
|
||||
#endif
|
||||
|
||||
//--Crypto Session API-----------------------------------------
|
||||
crysprOpenSSL_EVP_methods.open = crysprOpenSSL_EVP_Open;
|
||||
crysprOpenSSL_EVP_methods.close = crysprOpenSSL_EVP_Close;
|
||||
//--Keying material (km) encryption
|
||||
|
||||
#if CRYSPR_HAS_PBKDF2
|
||||
crysprOpenSSL_EVP_methods.km_pbkdf2 = crysprOpenSSL_EVP_KmPbkdf2;
|
||||
#else
|
||||
#error There is no default/fallback method for PBKDF2
|
||||
#endif
|
||||
// crysprOpenSSL_EVP_methods.km_setkey =
|
||||
#if CRYSPR_HAS_AESKWRAP
|
||||
crysprOpenSSL_EVP_methods.km_wrap = crysprOpenSSL_EVP_KmWrap;
|
||||
crysprOpenSSL_EVP_methods.km_unwrap = crysprOpenSSL_EVP_KmUnwrap;
|
||||
#endif
|
||||
|
||||
//--Media stream (ms) encryption
|
||||
// crysprOpenSSL_EVP_methods.ms_setkey =
|
||||
// crysprOpenSSL_EVP_methods.ms_encrypt =
|
||||
// crysprOpenSSL_EVP_methods.ms_decrypt =
|
||||
}
|
||||
return (&crysprOpenSSL_EVP_methods);
|
||||
}
|
67
trunk/3rdparty/srt-1-fit/haicrypt/cryspr-openssl-evp.h
vendored
Normal file
67
trunk/3rdparty/srt-1-fit/haicrypt/cryspr-openssl-evp.h
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Haivision Systems Inc.
|
||||
|
||||
2022-05-19 (jdube)
|
||||
OpenSSL EVP AES CRYSPR/4SRT (CRYypto Service PRovider for SRT).
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef CRYSPR_OPENSSL_H
|
||||
#define CRYSPR_OPENSSL_H
|
||||
|
||||
#include <openssl/evp.h> /* PKCS5_xxx() */
|
||||
#include <openssl/aes.h> /* AES_xxx() */
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL))
|
||||
#include <openssl/modes.h> /* CRYPTO_xxx() */
|
||||
#endif
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
/* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode
|
||||
if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode
|
||||
and provide the aes_ecb_cipher method.
|
||||
*/
|
||||
#define CRYSPR_HAS_AESCTR 1
|
||||
|
||||
/* Define CRYSPR_HAS_AESGCM to 1 if this CRYSPR has AES GCM cipher mode. OpenSSL EVP supports GCM.
|
||||
*/
|
||||
#define CRYSPR_HAS_AESGCM 1
|
||||
|
||||
/* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap
|
||||
if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods
|
||||
and provide the aes_ecb_cipher method .
|
||||
*/
|
||||
#if 1 // Force internal AES-WRAP (using AES-ECB) until implemented with EVP (OPENSSL_VERSION_NUMBER < 0x00xxxxxxL)
|
||||
#define CRYSPR_HAS_AESKWRAP 0
|
||||
#else
|
||||
#define CRYSPR_HAS_AESKWRAP 1
|
||||
#endif
|
||||
|
||||
/* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2
|
||||
if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method
|
||||
and provide the sha1_msg_digest method.
|
||||
*/
|
||||
#define CRYSPR_HAS_PBKDF2 1 /* Define to 1 if CRYSPR has Password-based Key Derivaion Function 2 */
|
||||
|
||||
/*
|
||||
#define CRYSPR_AESCTX to the CRYSPR specifix AES key context object.
|
||||
This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK
|
||||
It is set from hte keystring through CRYSPR_methods.aes_set_key and passed
|
||||
to CRYSPR_methods.aes_*.
|
||||
*/
|
||||
typedef EVP_CIPHER_CTX CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
|
||||
|
||||
struct tag_CRYSPR_methods* crysprOpenSSL_EVP(void);
|
||||
|
||||
#endif /* CRYSPR_OPENSSL_H */
|
|
@ -13,18 +13,23 @@
|
|||
written by
|
||||
Haivision Systems Inc.
|
||||
|
||||
2022-05-19 (jdube)
|
||||
CRYSPR2 adaptation
|
||||
2019-06-26 (jdube)
|
||||
OpenSSL CRYSPR/4SRT (CRYypto Service PRovider for SRT).
|
||||
OpenSSL Direct AES CRYSPR/4SRT (CRYypto Service PRovider for SRT).
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hcrypt.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct tag_crysprOpenSSL_AES_cb {
|
||||
CRYSPR_cb ccb;
|
||||
/* Add cryptolib specific data here */
|
||||
CRYSPR_cb ccb;
|
||||
/* Add cryptolib specific data here */
|
||||
#ifdef CRYSPR2
|
||||
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#endif
|
||||
} crysprOpenSSL_cb;
|
||||
|
||||
|
||||
|
@ -34,18 +39,21 @@ int crysprOpenSSL_Prng(unsigned char *rn, int len)
|
|||
}
|
||||
|
||||
int crysprOpenSSL_AES_SetKey(
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
|
||||
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
|
||||
const unsigned char *kstr, /* key sttring*/
|
||||
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
|
||||
CRYSPR_AESCTX *aes_key) /* CRYpto Service PRovider AES Key context */
|
||||
{
|
||||
(void)cipher_type;
|
||||
|
||||
if (bEncrypt) { /* Encrypt key */
|
||||
if (AES_set_encrypt_key(kstr, kstr_len * 8, aes_key)) {
|
||||
if (AES_set_encrypt_key(kstr, (int)(kstr_len * 8), aes_key)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) failed\n");
|
||||
return(-1);
|
||||
}
|
||||
} else { /* Decrypt key */
|
||||
if (AES_set_decrypt_key(kstr, kstr_len * 8, aes_key)) {
|
||||
if (AES_set_decrypt_key(kstr, (int)(kstr_len * 8), aes_key)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_decrypt_key(kek) failed\n");
|
||||
return(-1);
|
||||
}
|
||||
|
@ -123,7 +131,24 @@ int crysprOpenSSL_AES_CtrCipher(
|
|||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef CRYSPR2
|
||||
static CRYSPR_cb *crysprOpenSSL_Open(CRYSPR_methods *cryspr, size_t max_len)
|
||||
{
|
||||
crysprOpenSSL_cb *aes_data;
|
||||
|
||||
aes_data = (crysprOpenSSL_cb *)crysprHelper_Open(cryspr, sizeof(crysprOpenSSL_cb), max_len);
|
||||
if (NULL == aes_data) {
|
||||
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprOpenSSL_cb), max_len);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
|
||||
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
|
||||
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
|
||||
|
||||
return(&aes_data->ccb);
|
||||
}
|
||||
#endif /* CRYSPR2 */
|
||||
/*
|
||||
* Password-based Key Derivation Function
|
||||
*/
|
||||
|
@ -138,7 +163,7 @@ int crysprOpenSSL_KmPbkdf2(
|
|||
unsigned char *out) /* derived key */
|
||||
{
|
||||
(void)cryspr_cb;
|
||||
int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd,passwd_len,salt,salt_len,itr,key_len,out);
|
||||
int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd,(int)passwd_len,salt,(int)salt_len,itr,(int)key_len,out);
|
||||
return(rc == 1? 0 : -1);
|
||||
}
|
||||
|
||||
|
@ -148,8 +173,7 @@ int crysprOpenSSL_KmWrap(CRYSPR_cb *cryspr_cb,
|
|||
const unsigned char *sek,
|
||||
unsigned int seklen)
|
||||
{
|
||||
crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
|
||||
AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
|
||||
AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key
|
||||
|
||||
return(((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
|
||||
}
|
||||
|
@ -160,8 +184,7 @@ int crysprOpenSSL_KmUnwrap(
|
|||
const unsigned char *wrap,
|
||||
unsigned int wraplen)
|
||||
{
|
||||
crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
|
||||
AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
|
||||
AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key
|
||||
|
||||
return(((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0 : -1);
|
||||
}
|
||||
|
@ -192,7 +215,11 @@ CRYSPR_methods *crysprOpenSSL(void)
|
|||
#endif
|
||||
|
||||
//--Crypto Session API-----------------------------------------
|
||||
#ifdef CRYSPR2
|
||||
crysprOpenSSL_methods.open = crysprOpenSSL_Open;
|
||||
#else
|
||||
// crysprOpenSSL_methods.open =
|
||||
#endif
|
||||
// crysprOpenSSL_methods.close =
|
||||
//--Keying material (km) encryption
|
||||
|
||||
|
|
550
trunk/3rdparty/srt-1-fit/haicrypt/cryspr.c
vendored
550
trunk/3rdparty/srt-1-fit/haicrypt/cryspr.c
vendored
|
@ -14,7 +14,7 @@ written by
|
|||
Haivision Systems Inc.
|
||||
|
||||
2019-06-28 (jdube)
|
||||
CRYSPR/4SRT Initial implementation.
|
||||
CRYSPR/4SRT Initial implementation.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hcrypt.h"
|
||||
|
@ -25,109 +25,135 @@ written by
|
|||
|
||||
int crysprStub_Prng(unsigned char *rn, int len)
|
||||
{
|
||||
(void)rn;
|
||||
(void)len;
|
||||
return(0);
|
||||
(void)rn;
|
||||
(void)len;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int crysprStub_AES_SetKey(
|
||||
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
|
||||
const unsigned char *kstr, /* key sttring*/
|
||||
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
|
||||
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */
|
||||
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
|
||||
const unsigned char *kstr, /* key sttring*/
|
||||
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
|
||||
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
|
||||
{
|
||||
(void)bEncrypt;
|
||||
(void)kstr;
|
||||
(void)kstr_len;
|
||||
(void)aes_key;
|
||||
(void)cipher_type;
|
||||
(void)bEncrypt;
|
||||
(void)kstr;
|
||||
(void)kstr_len;
|
||||
(void)aes_key;
|
||||
|
||||
return(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int crysprStub_AES_EcbCipher(
|
||||
bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX *aes_key, /* AES context */
|
||||
const unsigned char *indata,/* src (clear text)*/
|
||||
size_t inlen, /* length */
|
||||
unsigned char *out_txt, /* dst (cipher text) */
|
||||
size_t *outlen) /* dst len */
|
||||
bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX *aes_key, /* AES context */
|
||||
const unsigned char *indata,/* src (clear text)*/
|
||||
size_t inlen, /* length */
|
||||
unsigned char *out_txt, /* dst (cipher text) */
|
||||
size_t *outlen) /* dst len */
|
||||
{
|
||||
(void)bEncrypt;
|
||||
(void)aes_key;
|
||||
(void)indata;
|
||||
(void)inlen;
|
||||
(void)out_txt;
|
||||
(void)outlen;
|
||||
(void)bEncrypt;
|
||||
(void)aes_key;
|
||||
(void)indata;
|
||||
(void)inlen;
|
||||
(void)out_txt;
|
||||
(void)outlen;
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int crysprStub_AES_CtrCipher(
|
||||
bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX *aes_key, /* AES context */
|
||||
unsigned char *iv, /* iv */
|
||||
const unsigned char *indata,/* src */
|
||||
size_t inlen, /* length */
|
||||
unsigned char *out_txt) /* dest */
|
||||
bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX *aes_key, /* AES context */
|
||||
unsigned char *iv, /* iv */
|
||||
const unsigned char *indata,/* src */
|
||||
size_t inlen, /* length */
|
||||
unsigned char *out_txt) /* dest */
|
||||
{
|
||||
(void)bEncrypt;
|
||||
(void)aes_key;
|
||||
(void)iv;
|
||||
(void)indata;
|
||||
(void)inlen;
|
||||
(void)out_txt;
|
||||
(void)bEncrypt;
|
||||
(void)aes_key;
|
||||
(void)iv;
|
||||
(void)indata;
|
||||
(void)inlen;
|
||||
(void)out_txt;
|
||||
|
||||
return(-1);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int crysprStub_AES_GCMCipher(
|
||||
bool bEncrypt, /* true:encrypt, false:decrypt */
|
||||
CRYSPR_AESCTX *aes_key, /* AES context */
|
||||
unsigned char *iv, /* iv */
|
||||
const unsigned char *aad, /* associated data */
|
||||
size_t aadlen,
|
||||
const unsigned char * indata,
|
||||
size_t inlen,
|
||||
unsigned char *out_txt,
|
||||
unsigned char* out_tag)
|
||||
{
|
||||
(void)bEncrypt;
|
||||
(void)aes_key;
|
||||
(void)iv;
|
||||
(void)aad;
|
||||
(void)aadlen;
|
||||
(void)indata;
|
||||
(void)inlen;
|
||||
(void)out_txt;
|
||||
(void)out_tag;
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
unsigned char *crysprStub_SHA1_MsgDigest(
|
||||
const unsigned char *m, /* in: message */
|
||||
size_t m_len, /* message length */
|
||||
unsigned char *md) /* out: message digest buffer *160 bytes */
|
||||
const unsigned char *m, /* in: message */
|
||||
size_t m_len, /* message length */
|
||||
unsigned char *md) /* out: message digest buffer *160 bytes */
|
||||
{
|
||||
(void)m;
|
||||
(void)m_len;
|
||||
(void)md;
|
||||
(void)m;
|
||||
(void)m_len;
|
||||
(void)md;
|
||||
|
||||
return(NULL);//return md;
|
||||
return(NULL);//return md;
|
||||
}
|
||||
|
||||
/*
|
||||
* Password-based Key Derivation Function
|
||||
*/
|
||||
int crysprStub_KmPbkdf2(
|
||||
CRYSPR_cb *cryspr_cb,
|
||||
char *passwd, /* passphrase */
|
||||
size_t passwd_len, /* passphrase len */
|
||||
unsigned char *salt, /* salt */
|
||||
size_t salt_len, /* salt_len */
|
||||
int itr, /* iterations */
|
||||
size_t key_len, /* key_len */
|
||||
unsigned char *out) /* derived key */
|
||||
CRYSPR_cb *cryspr_cb,
|
||||
char *passwd, /* passphrase */
|
||||
size_t passwd_len, /* passphrase len */
|
||||
unsigned char *salt, /* salt */
|
||||
size_t salt_len, /* salt_len */
|
||||
int itr, /* iterations */
|
||||
size_t key_len, /* key_len */
|
||||
unsigned char *out) /* derived key */
|
||||
{
|
||||
(void)cryspr_cb;
|
||||
(void)passwd;
|
||||
(void)passwd_len;
|
||||
(void)salt;
|
||||
(void)salt_len;
|
||||
(void)itr;
|
||||
(void)key_len;
|
||||
(void)out;
|
||||
(void)cryspr_cb;
|
||||
(void)passwd;
|
||||
(void)passwd_len;
|
||||
(void)salt;
|
||||
(void)salt_len;
|
||||
(void)itr;
|
||||
(void)key_len;
|
||||
(void)out;
|
||||
|
||||
/* >>Todo:
|
||||
* develop PBKDF2 using SHA1 primitive cryspr_cb->cryspr->sha1_msg_digest() for cryptolibs not providing it
|
||||
*/
|
||||
return(-1);
|
||||
/* >>Todo:
|
||||
* develop PBKDF2 using SHA1 primitive cryspr_cb->cryspr->sha1_msg_digest() for cryptolibs not providing it
|
||||
*/
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int crysprFallback_KmSetKey(CRYSPR_cb *cryspr_cb, bool bWrap, const unsigned char *kek, size_t kek_len)
|
||||
{
|
||||
CRYSPR_AESCTX *aes_kek = &cryspr_cb->aes_kek;
|
||||
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
|
||||
|
||||
if (cryspr_cb->cryspr->aes_set_key(bWrap, kek, kek_len, aes_kek)) {
|
||||
HCRYPT_LOG(LOG_ERR, "AES_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt");
|
||||
return(-1);
|
||||
}
|
||||
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESECB, bWrap, kek, kek_len, aes_kek)) {
|
||||
HCRYPT_LOG(LOG_ERR, "aes_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -142,7 +168,7 @@ static const unsigned char default_iv[] = {
|
|||
int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
unsigned int inlen)
|
||||
unsigned int inlen)
|
||||
{
|
||||
unsigned char *A, B[16], *R;
|
||||
const unsigned char *iv = default_iv;
|
||||
|
@ -163,7 +189,9 @@ int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
|
|||
memcpy(B + 8, R, 8);
|
||||
{
|
||||
size_t outlen = 16;
|
||||
cryspr_cb->cryspr->aes_ecb_cipher(true, &cryspr_cb->aes_kek, B, 16, B, &outlen);
|
||||
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
|
||||
|
||||
cryspr_cb->cryspr->aes_ecb_cipher(true, aes_kek, B, 16, B, &outlen);
|
||||
}
|
||||
A[7] ^= (unsigned char)(t & 0xff);
|
||||
if (t > 0xff)
|
||||
|
@ -176,13 +204,13 @@ int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
|
|||
}
|
||||
}
|
||||
memcpy(out, A, 8);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
unsigned int inlen)
|
||||
unsigned int inlen)
|
||||
{
|
||||
unsigned char *A, B[16], *R;
|
||||
const unsigned char *iv = default_iv;
|
||||
|
@ -211,7 +239,9 @@ int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
|
|||
memcpy(B + 8, R, 8);
|
||||
{
|
||||
size_t outlen = 16;
|
||||
cryspr_cb->cryspr->aes_ecb_cipher(false, &cryspr_cb->aes_kek, B, 16, B, &outlen);
|
||||
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
|
||||
|
||||
cryspr_cb->cryspr->aes_ecb_cipher(false, aes_kek, B, 16, B, &outlen);
|
||||
}
|
||||
memcpy(R, B + 8, 8);
|
||||
}
|
||||
|
@ -219,9 +249,9 @@ int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
|
|||
if (memcmp(A, iv, 8))
|
||||
{
|
||||
memset(out, 0, inlen);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char *_crysprFallback_GetOutbuf(CRYSPR_cb *cryspr_cb, size_t pfx_len, size_t out_len)
|
||||
|
@ -237,20 +267,23 @@ static unsigned char *_crysprFallback_GetOutbuf(CRYSPR_cb *cryspr_cb, size_t pfx
|
|||
return(out_buf);
|
||||
}
|
||||
|
||||
static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
|
||||
CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len)
|
||||
{
|
||||
CRYSPR_cb *cryspr_cb;
|
||||
unsigned char *membuf;
|
||||
size_t memsiz, padded_len = hcryptMsg_PaddedLen(max_len, 128/8);
|
||||
|
||||
HCRYPT_LOG(LOG_DEBUG, "%s", "Using OpenSSL AES\n");
|
||||
|
||||
memsiz = sizeof(*cryspr_cb) + (CRYSPR_OUTMSGMAX * padded_len);
|
||||
if(cb_len < sizeof(*cryspr_cb)) {
|
||||
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open() cb_len too small (%zd < %zd)n",
|
||||
cb_len, sizeof(*cryspr_cb));
|
||||
return(NULL);
|
||||
}
|
||||
memsiz = cb_len + (CRYSPR_OUTMSGMAX * padded_len);
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
memsiz += HCRYPT_CTR_STREAM_SZ;
|
||||
#endif /* !CRYSPR_HAS_AESCTR */
|
||||
|
||||
cryspr_cb = malloc(memsiz);
|
||||
cryspr_cb = calloc(1, memsiz);
|
||||
if (NULL == cryspr_cb) {
|
||||
HCRYPT_LOG(LOG_ERR, "malloc(%zd) failed\n", memsiz);
|
||||
return(NULL);
|
||||
|
@ -258,6 +291,9 @@ static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
|
|||
membuf = (unsigned char *)cryspr_cb;
|
||||
membuf += sizeof(*cryspr_cb);
|
||||
|
||||
/*reserve cryspr's private data that caller will initialize */
|
||||
membuf += (cb_len-sizeof(CRYSPR_cb));
|
||||
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
cryspr_cb->ctr_stream = membuf;
|
||||
membuf += HCRYPT_CTR_STREAM_SZ;
|
||||
|
@ -275,26 +311,42 @@ static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
|
|||
return(cryspr_cb);
|
||||
}
|
||||
|
||||
int crysprHelper_Close(CRYSPR_cb *cryspr_cb)
|
||||
{
|
||||
free(cryspr_cb);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
|
||||
{
|
||||
CRYSPR_cb *cryspr_cb;
|
||||
|
||||
cryspr_cb = crysprHelper_Open(cryspr, sizeof(CRYSPR_cb), max_len);
|
||||
return(cryspr_cb);
|
||||
}
|
||||
|
||||
static int crysprFallback_Close(CRYSPR_cb *cryspr_cb)
|
||||
{
|
||||
if (NULL != cryspr_cb) {
|
||||
free(cryspr_cb);
|
||||
}
|
||||
return(0);
|
||||
return(crysprHelper_Close(cryspr_cb));
|
||||
}
|
||||
|
||||
static int crysprFallback_MsSetKey(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, const unsigned char *key, size_t key_len)
|
||||
{
|
||||
CRYSPR_AESCTX *aes_sek = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; /* Ctx tells if it's for odd or even key */
|
||||
CRYSPR_AESCTX *aes_sek = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */
|
||||
|
||||
if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) /* Encrypt key */
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM) { /* AES GCM mode */
|
||||
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESGCM, (ctx->flags & HCRYPT_CTX_F_ENCRYPT) != 0, key, key_len, aes_sek)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n");
|
||||
return(-1);
|
||||
}
|
||||
} else if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) /* Encrypt key */
|
||||
|| (ctx->mode == HCRYPT_CTX_MODE_AESCTR)) { /* CTR mode decrypts using encryption methods */
|
||||
if (cryspr_cb->cryspr->aes_set_key(true, key, key_len, aes_sek)) {
|
||||
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, true, key, key_len, aes_sek)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n");
|
||||
return(-1);
|
||||
}
|
||||
} else { /* Decrypt key */
|
||||
if (cryspr_cb->cryspr->aes_set_key(false, key, key_len, aes_sek)) {
|
||||
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, false, key, key_len, aes_sek)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_decrypt_key(sek) failed\n");
|
||||
return(-1);
|
||||
}
|
||||
|
@ -372,71 +424,68 @@ static int crysprFallback_MsEncrypt(
|
|||
* to reserve room for unencrypted message header in output buffer
|
||||
*/
|
||||
pfx_len = ctx->msg_info->pfx_len;
|
||||
/* Extra 16 bytes are needed for an authentication tag in GCM. */
|
||||
const int aux_len = (ctx->mode == HCRYPT_CTX_MODE_AESGCM) ? HAICRYPT_AUTHTAG_MAX : 0;
|
||||
|
||||
/* Get buffer room from the internal circular output buffer */
|
||||
out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len);
|
||||
/* Auth tag produced by AES GCM. */
|
||||
unsigned char tag[HAICRYPT_AUTHTAG_MAX];
|
||||
|
||||
if (NULL != out_msg) {
|
||||
switch(ctx->mode) {
|
||||
case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
|
||||
/*
|
||||
* Get buffer room from the internal circular output buffer.
|
||||
* Reserve additional 16 bytes for auth tag in AES GCM mode when needed.
|
||||
*/
|
||||
out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len + aux_len);
|
||||
if (NULL == out_msg) {
|
||||
/* input data too big */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
switch(ctx->mode) {
|
||||
case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
|
||||
case HCRYPT_CTX_MODE_AESGCM:
|
||||
{
|
||||
/* Get current key (odd|even) from context */
|
||||
CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */
|
||||
|
||||
unsigned char iv[CRYSPR_AESBLKSZ];
|
||||
|
||||
/* Get input packet index (in network order) */
|
||||
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
|
||||
|
||||
/*
|
||||
* Compute the Initial Vector
|
||||
* IV (128-bit):
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 0s | pki | ctr |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* XOR
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | nonce +
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* pki (32-bit): packet index
|
||||
* ctr (16-bit): block counter
|
||||
* nonce (112-bit): number used once (salt)
|
||||
*/
|
||||
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
|
||||
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
|
||||
{
|
||||
const int iret = cryspr_cb->cryspr->aes_gcm_cipher(true, aes_key, iv, in_data[0].pfx, pfx_len, in_data[0].payload, in_data[0].len,
|
||||
&out_msg[pfx_len], tag);
|
||||
if (iret) {
|
||||
return(iret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if CRYSPR_HAS_AESCTR
|
||||
/* Get current key (odd|even) from context */
|
||||
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
|
||||
unsigned char iv[CRYSPR_AESBLKSZ];
|
||||
|
||||
/* Get input packet index (in network order) */
|
||||
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
|
||||
|
||||
/*
|
||||
* Compute the Initial Vector
|
||||
* IV (128-bit):
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 0s | pki | ctr |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* XOR
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | nonce +
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* pki (32-bit): packet index
|
||||
* ctr (16-bit): block counter
|
||||
* nonce (112-bit): number used once (salt)
|
||||
*/
|
||||
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
|
||||
|
||||
cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len,
|
||||
&out_msg[pfx_len]);
|
||||
#else /*CRYSPR_HAS_AESCTR*/
|
||||
/* Get current key (odd|even) from context */
|
||||
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
|
||||
unsigned char iv[CRYSPR_AESBLKSZ];
|
||||
int iret = 0;
|
||||
|
||||
/* Get input packet index (in network order) */
|
||||
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
|
||||
|
||||
/*
|
||||
* Compute the Initial Vector
|
||||
* IV (128-bit):
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 0s | pki | ctr |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* XOR
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | nonce +
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* pki (32-bit): packet index
|
||||
* ctr (16-bit): block counter
|
||||
* nonce (112-bit): number used once (salt)
|
||||
*/
|
||||
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
|
||||
|
||||
/* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */
|
||||
iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
|
||||
int iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
|
||||
if (iret) {
|
||||
return(iret);
|
||||
}
|
||||
|
@ -452,59 +501,29 @@ static int crysprFallback_MsEncrypt(
|
|||
return(iret);
|
||||
}
|
||||
#endif/*CRYSPR_HAS_AESCTR*/
|
||||
/* Prepend packet prefix (clear text) in output buffer */
|
||||
memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
/* CTR mode output length is same as input, no padding */
|
||||
out_len = in_data[0].len;
|
||||
break;
|
||||
}
|
||||
case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */
|
||||
memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len);
|
||||
memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
out_len = in_data[0].len;
|
||||
break;
|
||||
default:
|
||||
/* Unsupported cipher mode */
|
||||
return(-1);
|
||||
/* Prepend packet prefix (clear text) in output buffer */
|
||||
memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
/* CTR mode output length is same as input, no padding */
|
||||
out_len = in_data[0].len;
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
|
||||
{
|
||||
memcpy(out_msg + pfx_len + out_len, tag, sizeof(tag));
|
||||
out_len += sizeof(tag);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* input data too big */
|
||||
return(-1);
|
||||
case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */
|
||||
memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len);
|
||||
memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
out_len = in_data[0].len;
|
||||
break;
|
||||
default:
|
||||
/* Unsupported cipher mode */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (out_len > 0) {
|
||||
/* Encrypted messages have been produced */
|
||||
if (NULL == out_p) {
|
||||
/*
|
||||
* Application did not provided output buffer,
|
||||
* so copy encrypted message back in input buffer
|
||||
*/
|
||||
memcpy(in_data[0].pfx, out_msg, pfx_len);
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
|
||||
/* XOR KeyStream with input text directly in input buffer */
|
||||
hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
}else{
|
||||
/* Copy output data back in input buffer */
|
||||
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
}
|
||||
#else /* CRYSPR_HAS_AESCTR */
|
||||
/* Copy output data back in input buffer */
|
||||
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
#endif /* CRYSPR_HAS_AESCTR */
|
||||
} else {
|
||||
/* Copy header in output buffer if needed */
|
||||
if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
|
||||
hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len);
|
||||
}
|
||||
#endif /* CRYSPR_HAS_AESCTR */
|
||||
out_p[0] = out_msg;
|
||||
out_len_p[0] = pfx_len + out_len;
|
||||
*nbout_p = 1;
|
||||
}
|
||||
} else {
|
||||
if (out_len <= 0) {
|
||||
/*
|
||||
* Nothing out
|
||||
* This is not an error for implementations using deferred/async processing
|
||||
|
@ -514,6 +533,43 @@ static int crysprFallback_MsEncrypt(
|
|||
if (nbout_p != NULL) *nbout_p = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Encrypted messages have been produced */
|
||||
if (NULL == out_p) {
|
||||
/*
|
||||
* Application did not provided output buffer,
|
||||
* so copy encrypted message back in input buffer
|
||||
*/
|
||||
memcpy(in_data[0].pfx, out_msg, pfx_len);
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
|
||||
/* XOR KeyStream with input text directly in input buffer */
|
||||
hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
}else{
|
||||
/* Copy output data back in input buffer */
|
||||
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
}
|
||||
#else /* CRYSPR_HAS_AESCTR */
|
||||
/* Copy output data back in input buffer */
|
||||
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM) {
|
||||
// Encoding produced more payload (auth tag).
|
||||
return (int)out_len;
|
||||
}
|
||||
#endif /* CRYSPR_HAS_AESCTR */
|
||||
} else {
|
||||
/* Copy header in output buffer if needed */
|
||||
if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len);
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
|
||||
hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len);
|
||||
}
|
||||
#endif /* CRYSPR_HAS_AESCTR */
|
||||
out_p[0] = out_msg;
|
||||
out_len_p[0] = pfx_len + out_len;
|
||||
*nbout_p = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -534,10 +590,10 @@ static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
|
|||
if (NULL != out_txt) {
|
||||
switch(ctx->mode) {
|
||||
case HCRYPT_CTX_MODE_AESCTR:
|
||||
case HCRYPT_CTX_MODE_AESGCM:
|
||||
{
|
||||
#if CRYSPR_HAS_AESCTR
|
||||
/* Get current key (odd|even) from context */
|
||||
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
|
||||
CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx));
|
||||
unsigned char iv[CRYSPR_AESBLKSZ];
|
||||
|
||||
/* Get input packet index (in network order) */
|
||||
|
@ -561,54 +617,63 @@ static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
|
|||
*/
|
||||
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
|
||||
|
||||
cryspr_cb->cryspr->aes_ctr_cipher(false, aes_key, iv, in_data[0].payload, in_data[0].len,
|
||||
out_txt);
|
||||
out_len = in_data[0].len;
|
||||
#else /*CRYSPR_HAS_AESCTR*/
|
||||
/* Get current key (odd|even) from context */
|
||||
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
|
||||
unsigned char iv[CRYSPR_AESBLKSZ];
|
||||
int iret = 0;
|
||||
|
||||
/* Get input packet index (in network order) */
|
||||
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
|
||||
|
||||
/*
|
||||
* Compute the Initial Vector
|
||||
* IV (128-bit):
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 0s | pki | ctr |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* XOR
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | nonce +
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* pki (32-bit): packet index
|
||||
* ctr (16-bit): block counter
|
||||
* nonce (112-bit): number used once (salt)
|
||||
*/
|
||||
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
|
||||
|
||||
/* Create CtrStream. May be longer than in_len (next cipher block size boundary) */
|
||||
iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
|
||||
if (iret) {
|
||||
return(iret);
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
|
||||
{
|
||||
unsigned char* tag = in_data[0].payload + in_data[0].len - HAICRYPT_AUTHTAG_MAX;
|
||||
int liret = cryspr_cb->cryspr->aes_gcm_cipher(false, aes_key, iv, in_data[0].pfx, ctx->msg_info->pfx_len, in_data[0].payload, in_data[0].len - HAICRYPT_AUTHTAG_MAX,
|
||||
out_txt, tag);
|
||||
if (liret) {
|
||||
return(liret);
|
||||
}
|
||||
out_len = in_data[0].len - HAICRYPT_AUTHTAG_MAX;
|
||||
}
|
||||
/* Reserve output buffer for cryspr */
|
||||
out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, cryspr_cb->ctr_stream_len);
|
||||
else {
|
||||
#if CRYSPR_HAS_AESCTR
|
||||
cryspr_cb->cryspr->aes_ctr_cipher(false, aes_key, iv, in_data[0].payload, in_data[0].len,
|
||||
out_txt);
|
||||
out_len = in_data[0].len;
|
||||
#else /*CRYSPR_HAS_AESCTR*/
|
||||
|
||||
/* Create KeyStream (encrypt CtrStream) */
|
||||
iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
|
||||
/* Get input packet index (in network order) */
|
||||
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
|
||||
|
||||
/*
|
||||
* Compute the Initial Vector
|
||||
* IV (128-bit):
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 0s | pki | ctr |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* XOR
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | nonce +
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* pki (32-bit): packet index
|
||||
* ctr (16-bit): block counter
|
||||
* nonce (112-bit): number used once (salt)
|
||||
*/
|
||||
hcrypt_SetCtrIV((unsigned char*)&pki, ctx->salt, iv);
|
||||
|
||||
/* Create CtrStream. May be longer than in_len (next cipher block size boundary) */
|
||||
int liret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
|
||||
if (liret) {
|
||||
return(liret);
|
||||
}
|
||||
/* Reserve output buffer for cryspr */
|
||||
out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, cryspr_cb->ctr_stream_len);
|
||||
|
||||
/* Create KeyStream (encrypt CtrStream) */
|
||||
liret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
|
||||
cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
|
||||
out_txt, &out_len);
|
||||
if (iret) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "crysprNatural_AES_ecb_cipher(encrypt failed\n");
|
||||
return(iret);
|
||||
}
|
||||
if (liret) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "crysprNatural_AES_ecb_cipher(encrypt failed\n");
|
||||
return(liret);
|
||||
}
|
||||
|
||||
#endif /*CRYSPR_HAS_AESCTR*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HCRYPT_CTX_MODE_CLRTXT:
|
||||
|
@ -639,6 +704,7 @@ static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
|
|||
#else /* CRYSPR_HAS_AESCTR */
|
||||
/* Copy output data back in input buffer */
|
||||
memcpy(in_data[0].payload, out_txt, out_len);
|
||||
in_data->len = out_len;
|
||||
#endif /* CRYSPR_HAS_AESCTR */
|
||||
} else {
|
||||
/* Copy header in output buffer if needed */
|
||||
|
@ -684,9 +750,9 @@ CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr)
|
|||
cryspr->aes_set_key = crysprStub_AES_SetKey;
|
||||
cryspr->aes_ecb_cipher = crysprStub_AES_EcbCipher;
|
||||
cryspr->aes_ctr_cipher = crysprStub_AES_CtrCipher;
|
||||
cryspr->aes_gcm_cipher = crysprStub_AES_GCMCipher;
|
||||
cryspr->sha1_msg_digest = crysprStub_SHA1_MsgDigest;
|
||||
|
||||
|
||||
/* Crypto Session API */
|
||||
cryspr->open = crysprFallback_Open;
|
||||
cryspr->close = crysprFallback_Close;
|
||||
|
@ -705,5 +771,5 @@ CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr)
|
|||
|
||||
HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance(void)
|
||||
{
|
||||
return((HaiCrypt_Cryspr)cryspr4SRT());
|
||||
return((HaiCrypt_Cryspr)cryspr4SRT());
|
||||
}
|
||||
|
|
42
trunk/3rdparty/srt-1-fit/haicrypt/cryspr.h
vendored
42
trunk/3rdparty/srt-1-fit/haicrypt/cryspr.h
vendored
|
@ -39,24 +39,33 @@ extern "C" {
|
|||
#include "cryspr-config.h"
|
||||
|
||||
typedef struct tag_CRYSPR_cb {
|
||||
CRYSPR_AESCTX aes_kek; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#ifdef CRYSPR2
|
||||
CRYSPR_AESCTX *aes_kek; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX *aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#define CRYSPR_GETKEK(cb) ((cb)->aes_kek)
|
||||
#define CRYSPR_GETSEK(cb,kk) ((cb)->aes_sek[kk])
|
||||
#else /*CRYSPR2*/
|
||||
CRYSPR_AESCTX aes_kek; /* Key Encrypting Key (KEK) */
|
||||
CRYSPR_AESCTX aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */
|
||||
#define CRYSPR_GETKEK(cb) (&((cb)->aes_kek))
|
||||
#define CRYSPR_GETSEK(cb,kk) (&((cb)->aes_sek[kk]))
|
||||
#endif /*CRYSPR2*/
|
||||
|
||||
struct tag_CRYSPR_methods *cryspr;
|
||||
struct tag_CRYSPR_methods *cryspr;
|
||||
|
||||
#if !CRYSPR_HAS_AESCTR
|
||||
/* Reserve room to build the counter stream ourself */
|
||||
#define HCRYPT_CTR_BLK_SZ CRYSPR_AESBLKSZ
|
||||
#define HCRYPT_CTR_STREAM_SZ 2048
|
||||
unsigned char * ctr_stream;
|
||||
size_t ctr_stream_len; /* Content size */
|
||||
size_t ctr_stream_siz; /* Allocated length */
|
||||
unsigned char * ctr_stream;
|
||||
size_t ctr_stream_len; /* Content size */
|
||||
size_t ctr_stream_siz; /* Allocated length */
|
||||
#endif /* !CRYSPR_HAS_AESCTR */
|
||||
|
||||
#define CRYSPR_OUTMSGMAX 6
|
||||
uint8_t * outbuf; /* output circle buffer */
|
||||
size_t outbuf_ofs; /* write offset in circle buffer */
|
||||
size_t outbuf_siz; /* circle buffer size */
|
||||
uint8_t * outbuf; /* output circle buffer */
|
||||
size_t outbuf_ofs; /* write offset in circle buffer */
|
||||
size_t outbuf_siz; /* circle buffer size */
|
||||
} CRYSPR_cb;
|
||||
|
||||
typedef struct tag_CRYSPR_methods {
|
||||
|
@ -69,6 +78,7 @@ typedef struct tag_CRYSPR_methods {
|
|||
int rn_len);
|
||||
|
||||
int (*aes_set_key)(
|
||||
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */
|
||||
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
|
||||
const unsigned char *kstr,/* key string*/
|
||||
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
|
||||
|
@ -90,6 +100,17 @@ typedef struct tag_CRYSPR_methods {
|
|||
size_t inlen, /* src length */
|
||||
unsigned char *out_txt);/* dest */
|
||||
|
||||
int (*aes_gcm_cipher)(
|
||||
bool bEncrypt, /* true:encrypt false:decrypt (don't care with CTR) */
|
||||
CRYSPR_AESCTX* aes_key, /* ctx */
|
||||
unsigned char* iv, /* iv */
|
||||
const unsigned char* aad, /* associated data */
|
||||
size_t aadlen,
|
||||
const unsigned char* indata, /* src (clear text) */
|
||||
size_t inlen, /* src length */
|
||||
unsigned char* out_txt, /* dest */
|
||||
unsigned char* out_tag);
|
||||
|
||||
unsigned char *(*sha1_msg_digest)(
|
||||
const unsigned char *m, /* in: message */
|
||||
size_t m_len, /* message length */
|
||||
|
@ -194,6 +215,9 @@ typedef struct tag_CRYSPR_methods {
|
|||
|
||||
} CRYSPR_methods;
|
||||
|
||||
CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len);
|
||||
int crysprHelper_Close(CRYSPR_cb *cryspr_cb);
|
||||
|
||||
CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -23,5 +23,4 @@ hcrypt_rx.c
|
|||
hcrypt_sa.c
|
||||
hcrypt_tx.c
|
||||
hcrypt_xpt_srt.c
|
||||
hcrypt_xpt_sta.c
|
||||
haicrypt_log.cpp
|
||||
|
|
|
@ -21,5 +21,4 @@ hcrypt_rx.c
|
|||
hcrypt_sa.c
|
||||
hcrypt_tx.c
|
||||
hcrypt_xpt_srt.c
|
||||
hcrypt_xpt_sta.c
|
||||
haicrypt_log.cpp
|
||||
|
|
24
trunk/3rdparty/srt-1-fit/haicrypt/filelist-openssl-evp.maf
vendored
Normal file
24
trunk/3rdparty/srt-1-fit/haicrypt/filelist-openssl-evp.maf
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# HaiCrypt library contents
|
||||
|
||||
PUBLIC HEADERS
|
||||
haicrypt.h
|
||||
hcrypt_ctx.h
|
||||
hcrypt_msg.h
|
||||
|
||||
PRIVATE HEADERS
|
||||
hcrypt.h
|
||||
cryspr.h
|
||||
cryspr-openssl-evp.h
|
||||
haicrypt_log.h
|
||||
|
||||
SOURCES
|
||||
cryspr.c
|
||||
cryspr-openssl-evp.c
|
||||
hcrypt.c
|
||||
hcrypt_ctx_rx.c
|
||||
hcrypt_ctx_tx.c
|
||||
hcrypt_rx.c
|
||||
hcrypt_sa.c
|
||||
hcrypt_tx.c
|
||||
hcrypt_xpt_srt.c
|
||||
haicrypt_log.cpp
|
|
@ -21,5 +21,4 @@ hcrypt_rx.c
|
|||
hcrypt_sa.c
|
||||
hcrypt_tx.c
|
||||
hcrypt_xpt_srt.c
|
||||
hcrypt_xpt_sta.c
|
||||
haicrypt_log.cpp
|
||||
|
|
52
trunk/3rdparty/srt-1-fit/haicrypt/haicrypt.h
vendored
52
trunk/3rdparty/srt-1-fit/haicrypt/haicrypt.h
vendored
|
@ -27,32 +27,16 @@ written by
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// setup exports
|
||||
#if defined _WIN32 && !defined __MINGW__
|
||||
#ifdef HAICRYPT_DYNAMIC
|
||||
#ifdef HAICRYPT_EXPORTS
|
||||
#define HAICRYPT_API __declspec(dllexport)
|
||||
#else
|
||||
#define HAICRYPT_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define HAICRYPT_API
|
||||
#endif
|
||||
#else
|
||||
#define HAICRYPT_API
|
||||
#endif
|
||||
|
||||
typedef void *HaiCrypt_Cryspr;
|
||||
|
||||
HAICRYPT_API HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance (void); /* Return a default cryspr instance */
|
||||
HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance (void); /* Return a default cryspr instance */
|
||||
|
||||
#define HAICRYPT_CIPHER_BLK_SZ 16 /* AES Block Size */
|
||||
|
||||
#define HAICRYPT_PWD_MAX_SZ 80 /* MAX password (for Password-based Key Derivation) */
|
||||
#define HAICRYPT_KEY_MAX_SZ 32 /* MAX key */
|
||||
#define HAICRYPT_SECRET_MAX_SZ (HAICRYPT_PWD_MAX_SZ > HAICRYPT_KEY_MAX_SZ ? HAICRYPT_PWD_MAX_SZ : HAICRYPT_KEY_MAX_SZ)
|
||||
|
||||
#define HAICRYPT_AUTHTAG_MAX 16 /* maximum length of the auth tag (e.g. GCM) */
|
||||
|
||||
#define HAICRYPT_SALT_SZ 16
|
||||
|
||||
|
@ -76,6 +60,7 @@ typedef struct {
|
|||
#define HAICRYPT_CFG_F_TX 0x01 /* !TX -> RX */
|
||||
#define HAICRYPT_CFG_F_CRYPTO 0x02 /* Perform crypto Tx:Encrypt Rx:Decrypt */
|
||||
#define HAICRYPT_CFG_F_FEC 0x04 /* Do Forward Error Correction */
|
||||
#define HAICRYPT_CFG_F_GCM 0x08 /* Use AES-GCM */
|
||||
unsigned flags;
|
||||
|
||||
HaiCrypt_Secret secret; /* Security Association */
|
||||
|
@ -108,26 +93,31 @@ typedef struct hcrypt_Session_str* HaiCrypt_Handle;
|
|||
|
||||
|
||||
|
||||
HAICRYPT_API int HaiCrypt_SetLogLevel(int level, int logfa);
|
||||
int HaiCrypt_SetLogLevel(int level, int logfa);
|
||||
|
||||
HAICRYPT_API int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc);
|
||||
HAICRYPT_API int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc);
|
||||
HAICRYPT_API int HaiCrypt_Close(HaiCrypt_Handle hhc);
|
||||
HAICRYPT_API int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_p);
|
||||
HAICRYPT_API int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
|
||||
void *out_p[], size_t out_len_p[], int maxout);
|
||||
HAICRYPT_API int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
|
||||
void *out_p[], size_t out_len_p[], int maxout);
|
||||
int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc);
|
||||
int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc);
|
||||
int HaiCrypt_Close(HaiCrypt_Handle hhc);
|
||||
int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_p);
|
||||
int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
|
||||
void *out_p[], size_t out_len_p[], int maxout);
|
||||
int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
|
||||
void *out_p[], size_t out_len_p[], int maxout);
|
||||
|
||||
HAICRYPT_API int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc);
|
||||
HAICRYPT_API int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout);
|
||||
HAICRYPT_API int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
|
||||
HAICRYPT_API int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
|
||||
int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc);
|
||||
int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout);
|
||||
int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
|
||||
int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
|
||||
|
||||
/// @brief Check if the crypto service provider supports AES GCM.
|
||||
/// @return returns 1 if AES GCM is supported, 0 otherwise.
|
||||
int HaiCrypt_IsAESGCM_Supported(void);
|
||||
|
||||
/* Status values */
|
||||
|
||||
#define HAICRYPT_ERROR -1
|
||||
#define HAICRYPT_ERROR_WRONG_SECRET -2
|
||||
#define HAICRYPT_ERROR_CIPHER -3
|
||||
#define HAICRYPT_OK 0
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#if ENABLE_HAICRYPT_LOGGING
|
||||
|
||||
#include "haicrypt_log.h"
|
||||
|
||||
#include "hcrypt.h"
|
||||
#include "haicrypt.h"
|
||||
#include "../srtcore/srt.h"
|
||||
|
@ -18,7 +20,7 @@
|
|||
extern srt_logging::LogConfig srt_logger_config;
|
||||
|
||||
// LOGFA symbol defined in srt.h
|
||||
srt_logging::Logger hclog(SRT_LOGFA_HAICRYPT, srt_logger_config, "SRT.k");
|
||||
srt_logging::Logger hclog(SRT_LOGFA_HAICRYPT, srt_logger_config, "SRT.hc");
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -42,10 +44,10 @@ int HaiCrypt_SetLogLevel(int level, int logfa)
|
|||
#define HAICRYPT_DEFINE_LOG_DISPATCHER(LOGLEVEL, dispatcher) \
|
||||
int HaiCrypt_LogF_##LOGLEVEL ( const char* file, int line, const char* function, const char* format, ...) \
|
||||
{ \
|
||||
va_list ap; \
|
||||
va_start(ap, format); \
|
||||
srt_logging::LogDispatcher& lg = hclog.dispatcher; \
|
||||
if (!lg.CheckEnabled()) return -1; \
|
||||
va_list ap; \
|
||||
va_start(ap, format); \
|
||||
lg().setloc(file, line, function).vform(format, ap); \
|
||||
va_end(ap); \
|
||||
return 0; \
|
||||
|
@ -97,12 +99,7 @@ void HaiCrypt_DumpConfig(const HaiCrypt_Cfg* cfg)
|
|||
LOGC(hclog.Debug, log << "CFG DUMP: flags=" << cfg_flags.str()
|
||||
<< " xport=" << (cfg->xport == HAICRYPT_XPT_SRT ? "SRT" : "INVALID")
|
||||
<< " cipher="
|
||||
<< (cfg->cipher == HaiCryptCipher_OpenSSL_EVP_CTR() ? "OSSL-EVP-CTR":
|
||||
cfg->cipher == HaiCryptCipher_OpenSSL_AES() ? "OSSL-AES":
|
||||
// This below is used as the only one when Nettle is used. When OpenSSL
|
||||
// is used, one of the above will trigger, and the one below will then never trigger.
|
||||
cfg->cipher == HaiCryptCipher_Get_Instance() ? "Nettle-AES":
|
||||
"UNKNOWN")
|
||||
<< CRYSPR_IMPL_DESC
|
||||
<< " key_len=" << cfg->key_len << " data_max_len=" << cfg->data_max_len);
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef IMC__HAICRYPT_LOG_H
|
||||
#define IMC__HAICRYPT_LOG_H
|
||||
#ifndef INC_SRT_HAICRYPT_LOG_H
|
||||
#define INC_SRT_HAICRYPT_LOG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -21,7 +21,7 @@ HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_EMERG);
|
|||
|
||||
#define HCRYPT_LOG_INIT()
|
||||
#define HCRYPT_LOG_EXIT()
|
||||
#define HCRYPT_LOG(lvl, fmt, ...) HaiCrypt_LogF_##lvl (__FILE__, __LINE__, __FUNCTION__, fmt, __VA_ARGS__)
|
||||
#define HCRYPT_LOG(lvl, ...) HaiCrypt_LogF_##lvl (__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
#if ENABLE_HAICRYPT_LOGGING == 2
|
||||
#define HCRYPT_DEV 1
|
||||
|
|
24
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt.c
vendored
24
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt.c
vendored
|
@ -74,10 +74,6 @@ static hcrypt_Session* sHaiCrypt_PrepareHandle(const HaiCrypt_Cfg* cfg, HaiCrypt
|
|||
|
||||
/* Setup transport packet info */
|
||||
switch (cfg->xport) {
|
||||
case HAICRYPT_XPT_STANDALONE:
|
||||
crypto->se = HCRYPT_SE_TSUDP;
|
||||
crypto->msg_info = hcryptMsg_STA_MsgInfo();
|
||||
break;
|
||||
case HAICRYPT_XPT_SRT:
|
||||
crypto->se = HCRYPT_SE_TSSRT;
|
||||
crypto->msg_info = hcryptMsg_SRT_MsgInfo();
|
||||
|
@ -160,7 +156,7 @@ int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
|
|||
|| hcryptCtx_Tx_Init(crypto, &crypto->ctx_pair[1], cfg)) {
|
||||
free(crypto);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
/* Generate keys for first (default) context */
|
||||
if (hcryptCtx_Tx_Rekey(crypto, &crypto->ctx_pair[0])) {
|
||||
free(crypto);
|
||||
|
@ -200,6 +196,9 @@ int HaiCrypt_ExtractConfig(HaiCrypt_Handle hhcSrc, HaiCrypt_Cfg* pcfg)
|
|||
pcfg->flags = HAICRYPT_CFG_F_CRYPTO;
|
||||
if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) == HCRYPT_CTX_F_ENCRYPT)
|
||||
pcfg->flags |= HAICRYPT_CFG_F_TX;
|
||||
|
||||
if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
|
||||
pcfg->flags |= HAICRYPT_CFG_F_GCM;
|
||||
|
||||
/* Set this explicitly - this use of this library is SRT only. */
|
||||
pcfg->xport = HAICRYPT_XPT_SRT;
|
||||
|
@ -241,7 +240,8 @@ int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handl
|
|||
|
||||
if (tx) {
|
||||
HaiCrypt_Cfg crypto_config;
|
||||
HaiCrypt_ExtractConfig(hhcSrc, &crypto_config);
|
||||
if (-1 == HaiCrypt_ExtractConfig(hhcSrc, &crypto_config))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Just invert the direction written in flags and use the
|
||||
|
@ -307,8 +307,7 @@ int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handl
|
|||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/* Configure contexts */
|
||||
/* Configure contexts. Note that GCM mode has been already copied from the source context. */
|
||||
if (hcryptCtx_Rx_Init(cryptoClone, &cryptoClone->ctx_pair[0], NULL)
|
||||
|| hcryptCtx_Rx_Init(cryptoClone, &cryptoClone->ctx_pair[1], NULL)) {
|
||||
free(cryptoClone);
|
||||
|
@ -340,3 +339,12 @@ int HaiCrypt_Close(HaiCrypt_Handle hhc)
|
|||
HCRYPT_LOG_EXIT();
|
||||
return rc;
|
||||
}
|
||||
|
||||
int HaiCrypt_IsAESGCM_Supported(void)
|
||||
{
|
||||
#if CRYSPR_HAS_AESGCM
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
19
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt.h
vendored
19
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt.h
vendored
|
@ -24,18 +24,14 @@ written by
|
|||
MINGW-W64 Build.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef HCRYPT_H
|
||||
#define HCRYPT_H
|
||||
#ifndef INC_SRT_HCRYPT_H
|
||||
#define INC_SRT_HCRYPT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4267)
|
||||
#pragma warning(disable:4018)
|
||||
#endif
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
@ -163,7 +159,18 @@ int hcryptCtx_Tx_AsmKM(hcrypt_Session *crypto, hcrypt_Ctx *ctx, unsigned char *a
|
|||
int hcryptCtx_Tx_ManageKM(hcrypt_Session *crypto);
|
||||
int hcryptCtx_Tx_InjectKM(hcrypt_Session *crypto, void *out_p[], size_t out_len_p[], int maxout);
|
||||
|
||||
/// @brief Initialize receiving crypto context.
|
||||
/// @param crypto library instance handle.
|
||||
/// @param ctx additional crypto context.
|
||||
/// @param cfg crypto configuration.
|
||||
/// @return -1 on error, 0 otherwise.
|
||||
int hcryptCtx_Rx_Init(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Cfg *cfg);
|
||||
|
||||
/// @brief Parse an incoming message related to cryptography module.
|
||||
/// @param crypto library instance handle.
|
||||
/// @param msg a message to parse.
|
||||
/// @param msg_len length of the message in bytes.
|
||||
/// @return 0 on success; -3 on cipher mode mismatch; -2 on unmatched shared secret; -1 on other failures.
|
||||
int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *msg, size_t msg_len);
|
||||
|
||||
#endif /* HCRYPT_H */
|
||||
|
|
|
@ -45,7 +45,7 @@ typedef struct {
|
|||
typedef struct tag_hcrypt_Ctx {
|
||||
struct tag_hcrypt_Ctx * alt; /* Alternative ctx (even/odd) */
|
||||
|
||||
#define HCRYPT_CTX_F_MSG 0x00FF /* Aligned wiht message header flags */
|
||||
#define HCRYPT_CTX_F_MSG 0x00FF /* Aligned with message header flags */
|
||||
#define HCRYPT_CTX_F_eSEK HCRYPT_MSG_F_eSEK
|
||||
#define HCRYPT_CTX_F_oSEK HCRYPT_MSG_F_oSEK
|
||||
#define HCRYPT_CTX_F_xSEK HCRYPT_MSG_F_xSEK
|
||||
|
@ -68,6 +68,7 @@ typedef struct tag_hcrypt_Ctx {
|
|||
#define HCRYPT_CTX_MODE_AESECB 1 /* Electronic Code Book mode */
|
||||
#define HCRYPT_CTX_MODE_AESCTR 2 /* Counter mode */
|
||||
#define HCRYPT_CTX_MODE_AESCBC 3 /* Cipher-block chaining mode */
|
||||
#define HCRYPT_CTX_MODE_AESGCM 4 /* AES GCM authenticated encryption */
|
||||
unsigned mode;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -14,9 +14,9 @@ written by
|
|||
Haivision Systems Inc.
|
||||
|
||||
2011-06-23 (jdube)
|
||||
HaiCrypt initial implementation.
|
||||
HaiCrypt initial implementation.
|
||||
2014-03-11 (jdube)
|
||||
Adaptation for SRT.
|
||||
Adaptation for SRT.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <string.h> /* memcpy */
|
||||
|
@ -24,16 +24,18 @@ written by
|
|||
|
||||
int hcryptCtx_Rx_Init(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Cfg *cfg)
|
||||
{
|
||||
ctx->mode = HCRYPT_CTX_MODE_AESCTR;
|
||||
ctx->status = HCRYPT_CTX_S_INIT;
|
||||
if (cfg) {
|
||||
ctx->mode = (cfg->flags & HAICRYPT_CFG_F_GCM) ? HCRYPT_CTX_MODE_AESGCM : HCRYPT_CTX_MODE_AESCTR;
|
||||
}
|
||||
ctx->status = HCRYPT_CTX_S_INIT;
|
||||
|
||||
ctx->msg_info = crypto->msg_info;
|
||||
ctx->msg_info = crypto->msg_info;
|
||||
|
||||
if (cfg && hcryptCtx_SetSecret(crypto, ctx, &cfg->secret)) {
|
||||
return(-1);
|
||||
}
|
||||
ctx->status = HCRYPT_CTX_S_SARDY;
|
||||
return(0);
|
||||
if (cfg && hcryptCtx_SetSecret(crypto, ctx, &cfg->secret)) {
|
||||
return(-1);
|
||||
}
|
||||
ctx->status = HCRYPT_CTX_S_SARDY;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int hcryptCtx_Rx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, unsigned char *sek, size_t sek_len)
|
||||
|
@ -98,9 +100,31 @@ int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *km_msg, size_t m
|
|||
}
|
||||
|
||||
/* Check options support */
|
||||
if ((HCRYPT_CIPHER_AES_CTR != km_msg[HCRYPT_MSG_KM_OFS_CIPHER])
|
||||
|| (HCRYPT_AUTH_NONE != km_msg[HCRYPT_MSG_KM_OFS_AUTH])) {
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported option\n");
|
||||
if (HCRYPT_CIPHER_AES_CTR != km_msg[HCRYPT_MSG_KM_OFS_CIPHER]
|
||||
&& HCRYPT_CIPHER_AES_GCM != km_msg[HCRYPT_MSG_KM_OFS_CIPHER])
|
||||
{
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported cipher\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
#if !CRYSPR_HAS_AESGCM
|
||||
/* Only OpenSSL EVP crypto provider allows the use of GCM.Add this condition. Reject if GCM is not supported by the CRYSPR. */
|
||||
if (HCRYPT_CIPHER_AES_GCM == km_msg[HCRYPT_MSG_KM_OFS_CIPHER])
|
||||
{
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported GCM cipher\n");
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (HCRYPT_CIPHER_AES_GCM == km_msg[HCRYPT_MSG_KM_OFS_CIPHER]
|
||||
&& HCRYPT_AUTH_AES_GCM != km_msg[HCRYPT_MSG_KM_OFS_AUTH]) {
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg GCM auth method was expected.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (HCRYPT_CIPHER_AES_CTR == km_msg[HCRYPT_MSG_KM_OFS_CIPHER]
|
||||
&& HCRYPT_AUTH_NONE != km_msg[HCRYPT_MSG_KM_OFS_AUTH]) {
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported auth method\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
@ -144,6 +168,13 @@ int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *km_msg, size_t m
|
|||
do_pbkdf = 1; /* Impact on password derived kek */
|
||||
}
|
||||
|
||||
/* Check cipher mode */
|
||||
if (ctx->mode != km_msg[HCRYPT_MSG_KM_OFS_CIPHER])
|
||||
{
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "cipher mode mismatch\n");
|
||||
return(-3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Regenerate KEK if it is password derived
|
||||
* and Salt or SEK length changed
|
||||
|
@ -159,7 +190,7 @@ int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *km_msg, size_t m
|
|||
/* Unwrap SEK(s) and set in context */
|
||||
if (0 > crypto->cryspr->km_unwrap(crypto->cryspr_cb, seks,
|
||||
&km_msg[HCRYPT_MSG_KM_OFS_SALT + salt_len],
|
||||
(sek_cnt * sek_len) + HAICRYPT_WRAPKEY_SIGN_SZ)) {
|
||||
(unsigned int)((sek_cnt * sek_len) + HAICRYPT_WRAPKEY_SIGN_SZ))) {
|
||||
HCRYPT_LOG(LOG_WARNING, "%s", "unwrap key failed\n");
|
||||
return(-2); //Report unmatched shared secret
|
||||
}
|
||||
|
@ -184,7 +215,6 @@ int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *km_msg, size_t m
|
|||
alt->salt_len = salt_len;
|
||||
|
||||
if (kek_len) { /* New or changed KEK */
|
||||
// memcpy(&alt->aes_kek, &ctx->aes_kek, sizeof(alt->aes_kek));
|
||||
alt->status = HCRYPT_CTX_S_SARDY;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,18 +14,18 @@ written by
|
|||
Haivision Systems Inc.
|
||||
|
||||
2011-06-23 (jdube)
|
||||
HaiCrypt initial implementation.
|
||||
HaiCrypt initial implementation.
|
||||
2014-03-11 (jdube)
|
||||
Adaptation for SRT.
|
||||
Adaptation for SRT.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <string.h> /* memcpy */
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <win/wintime.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <win/wintime.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include "hcrypt.h"
|
||||
|
||||
|
@ -33,7 +33,7 @@ int hcryptCtx_Tx_Init(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Cf
|
|||
{
|
||||
ctx->cfg.key_len = cfg->key_len;
|
||||
|
||||
ctx->mode = HCRYPT_CTX_MODE_AESCTR;
|
||||
ctx->mode = (cfg->flags & HAICRYPT_CFG_F_GCM) ? HCRYPT_CTX_MODE_AESGCM : HCRYPT_CTX_MODE_AESCTR;
|
||||
ctx->status = HCRYPT_CTX_S_INIT;
|
||||
|
||||
ctx->msg_info = crypto->msg_info;
|
||||
|
@ -52,14 +52,14 @@ int hcryptCtx_Tx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx)
|
|||
|
||||
/* Generate Salt */
|
||||
ctx->salt_len = HAICRYPT_SALT_SZ;
|
||||
if (0 > (iret = crypto->cryspr->prng(ctx->salt, ctx->salt_len))) {
|
||||
if (0 > (iret = crypto->cryspr->prng(ctx->salt, (int)ctx->salt_len))) {
|
||||
HCRYPT_LOG(LOG_ERR, "PRNG(salt[%zd]) failed\n", ctx->salt_len);
|
||||
return(iret);
|
||||
}
|
||||
|
||||
/* Generate SEK */
|
||||
ctx->sek_len = ctx->cfg.key_len;
|
||||
if (0 > (iret = crypto->cryspr->prng(ctx->sek, ctx->sek_len))) {
|
||||
if (0 > (iret = crypto->cryspr->prng(ctx->sek, (int)ctx->sek_len))) {
|
||||
HCRYPT_LOG(LOG_ERR, "PRNG(sek[%zd] failed\n", ctx->sek_len);
|
||||
return(iret);
|
||||
}
|
||||
|
@ -74,9 +74,10 @@ int hcryptCtx_Tx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx)
|
|||
HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
|
||||
|
||||
/* Regenerate KEK if Password-based (uses newly generated salt and sek_len) */
|
||||
if ((0 < ctx->cfg.pwd_len)
|
||||
&& (0 > (iret = hcryptCtx_GenSecret(crypto, ctx)))) {
|
||||
return(iret);
|
||||
if (0 < ctx->cfg.pwd_len) {
|
||||
iret = hcryptCtx_GenSecret(crypto, ctx);
|
||||
if (iret < 0)
|
||||
return(iret);
|
||||
}
|
||||
|
||||
/* Assemble the new Keying Material message */
|
||||
|
@ -106,22 +107,22 @@ int hcryptCtx_Tx_CloneKey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const hcrypt_
|
|||
|
||||
ASSERT(HCRYPT_CTX_S_SARDY <= ctx->status);
|
||||
|
||||
const hcrypt_Ctx* ctxSrc = cryptoSrc->ctx;
|
||||
if (!ctxSrc)
|
||||
{
|
||||
/* Probbly the context is not yet completely initialized, so
|
||||
* use blindly the first context from the pair
|
||||
*/
|
||||
ctxSrc = &cryptoSrc->ctx_pair[0];
|
||||
}
|
||||
const hcrypt_Ctx* ctxSrc = cryptoSrc->ctx;
|
||||
if (!ctxSrc)
|
||||
{
|
||||
/* Probbly the context is not yet completely initialized, so
|
||||
* use blindly the first context from the pair
|
||||
*/
|
||||
ctxSrc = &cryptoSrc->ctx_pair[0];
|
||||
}
|
||||
|
||||
/* Copy SALT (instead of generating) */
|
||||
ctx->salt_len = ctxSrc->salt_len;
|
||||
memcpy(ctx->salt, ctxSrc->salt, ctx->salt_len);
|
||||
/* Copy SALT (instead of generating) */
|
||||
ctx->salt_len = ctxSrc->salt_len;
|
||||
memcpy(ctx->salt, ctxSrc->salt, ctx->salt_len);
|
||||
|
||||
/* Copy SEK */
|
||||
ctx->sek_len = ctxSrc->sek_len;
|
||||
memcpy(ctx->sek, ctxSrc->sek, ctx->sek_len);
|
||||
/* Copy SEK */
|
||||
ctx->sek_len = ctxSrc->sek_len;
|
||||
memcpy(ctx->sek, ctxSrc->sek, ctx->sek_len);
|
||||
|
||||
/* Set SEK in cryspr */
|
||||
if (crypto->cryspr->ms_setkey(crypto->cryspr_cb, ctx, ctx->sek, ctx->sek_len)) {
|
||||
|
@ -133,11 +134,12 @@ int hcryptCtx_Tx_CloneKey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const hcrypt_
|
|||
HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
|
||||
|
||||
/* Regenerate KEK if Password-based (uses newly generated salt and sek_len) */
|
||||
/* (note for CloneKey imp: it's expected that the same passphrase-salt pair
|
||||
shall generate the same KEK. GenSecret also prints the KEK */
|
||||
if ((0 < ctx->cfg.pwd_len)
|
||||
&& (0 > (iret = hcryptCtx_GenSecret(crypto, ctx)))) {
|
||||
return(iret);
|
||||
/* (note for CloneKey imp: it's expected that the same passphrase-salt pair
|
||||
shall generate the same KEK. GenSecret also prints the KEK */
|
||||
if (0 < ctx->cfg.pwd_len) {
|
||||
iret = hcryptCtx_GenSecret(crypto, ctx);
|
||||
if (iret < 0)
|
||||
return(iret);
|
||||
}
|
||||
|
||||
/* Assemble the new Keying Material message */
|
||||
|
@ -193,7 +195,7 @@ int hcryptCtx_Tx_Refresh(hcrypt_Session *crypto)
|
|||
|
||||
HCRYPT_LOG(LOG_DEBUG, "refresh/generate SEK. salt_len=%d sek_len=%d\n", (int)new_ctx->salt_len, (int)new_ctx->sek_len);
|
||||
|
||||
if (0 > crypto->cryspr->prng(new_ctx->sek, new_ctx->sek_len)) {
|
||||
if (0 > crypto->cryspr->prng(new_ctx->sek, (int)new_ctx->sek_len)) {
|
||||
HCRYPT_LOG(LOG_ERR, "PRNG(sek[%zd] failed\n", new_ctx->sek_len);
|
||||
return(-1);
|
||||
}
|
||||
|
@ -297,9 +299,9 @@ int hcryptCtx_Tx_AsmKM(hcrypt_Session *crypto, hcrypt_Ctx *ctx, unsigned char *a
|
|||
2 == sek_cnt ? HCRYPT_MSG_F_xSEK : (ctx->flags & HCRYPT_MSG_F_xSEK));
|
||||
|
||||
/* crypto->KMmsg_cache[4..7]: KEKI=0 */
|
||||
km_msg[HCRYPT_MSG_KM_OFS_CIPHER] = HCRYPT_CIPHER_AES_CTR;
|
||||
km_msg[HCRYPT_MSG_KM_OFS_AUTH] = HCRYPT_AUTH_NONE;
|
||||
km_msg[HCRYPT_MSG_KM_OFS_SE] = crypto->se;
|
||||
km_msg[HCRYPT_MSG_KM_OFS_CIPHER] = (ctx->mode == HCRYPT_CTX_MODE_AESGCM) ? HCRYPT_CIPHER_AES_GCM : HCRYPT_CIPHER_AES_CTR;
|
||||
km_msg[HCRYPT_MSG_KM_OFS_AUTH] = (ctx->mode == HCRYPT_CTX_MODE_AESGCM) ? HCRYPT_AUTH_AES_GCM : HCRYPT_AUTH_NONE;
|
||||
km_msg[HCRYPT_MSG_KM_OFS_SE] = (char) crypto->se;
|
||||
hcryptMsg_KM_SetSaltLen(km_msg, ctx->salt_len);
|
||||
hcryptMsg_KM_SetSekLen(km_msg, ctx->sek_len);
|
||||
|
||||
|
@ -320,7 +322,7 @@ int hcryptCtx_Tx_AsmKM(hcrypt_Session *crypto, hcrypt_Ctx *ctx, unsigned char *a
|
|||
}
|
||||
if (0 > crypto->cryspr->km_wrap(crypto->cryspr_cb,
|
||||
&km_msg[HCRYPT_MSG_KM_OFS_SALT + ctx->salt_len],
|
||||
seks, sek_cnt * ctx->sek_len)) {
|
||||
seks, (unsigned int)(sek_cnt * ctx->sek_len))) {
|
||||
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "wrap key failed\n");
|
||||
return(-1);
|
||||
|
@ -336,8 +338,8 @@ int hcryptCtx_Tx_ManageKM(hcrypt_Session *crypto)
|
|||
ASSERT(NULL != ctx);
|
||||
|
||||
HCRYPT_LOG(LOG_DEBUG, "KM[%d] KEY STATUS: pkt_cnt=%u against ref.rate=%u and pre.announce=%u\n",
|
||||
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2,
|
||||
ctx->pkt_cnt, crypto->km.refresh_rate, crypto->km.pre_announce);
|
||||
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2,
|
||||
ctx->pkt_cnt, crypto->km.refresh_rate, crypto->km.pre_announce);
|
||||
|
||||
if ((ctx->pkt_cnt > crypto->km.refresh_rate)
|
||||
|| (ctx->pkt_cnt == 0)) { //rolled over
|
||||
|
@ -358,7 +360,7 @@ int hcryptCtx_Tx_ManageKM(hcrypt_Session *crypto)
|
|||
* prepare next SEK for announcement
|
||||
*/
|
||||
hcryptCtx_Tx_Refresh(crypto);
|
||||
|
||||
|
||||
HCRYPT_LOG(LOG_INFO, "KM[%d] Pre-announced\n",
|
||||
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2);
|
||||
|
||||
|
|
|
@ -122,8 +122,10 @@ typedef struct {
|
|||
#define HCRYPT_CIPHER_AES_ECB 1
|
||||
#define HCRYPT_CIPHER_AES_CTR 2
|
||||
#define HCRYPT_CIPHER_AES_CBC 3
|
||||
#define HCRYPT_CIPHER_AES_GCM 4
|
||||
|
||||
#define HCRYPT_AUTH_NONE 0
|
||||
#define HCRYPT_AUTH_AES_GCM 1
|
||||
|
||||
#define HCRYPT_SE_TSUDP 1
|
||||
hcrypt_MsgInfo * hcryptMsg_STA_MsgInfo(void);
|
||||
|
@ -148,8 +150,8 @@ typedef struct {
|
|||
#define hcryptMsg_KM_GetSaltLen(msg) (size_t)((msg)[HCRYPT_MSG_KM_OFS_SLEN] * 4)
|
||||
#define hcryptMsg_KM_GetSekLen(msg) (size_t)((msg)[HCRYPT_MSG_KM_OFS_KLEN] * 4)
|
||||
|
||||
#define hcryptMsg_KM_SetSaltLen(msg,len)do {(msg)[HCRYPT_MSG_KM_OFS_SLEN] = (len)/4;} while(0)
|
||||
#define hcryptMsg_KM_SetSekLen(msg,len) do {(msg)[HCRYPT_MSG_KM_OFS_KLEN] = (len)/4;} while(0)
|
||||
#define hcryptMsg_KM_SetSaltLen(msg,len)do {(msg)[HCRYPT_MSG_KM_OFS_SLEN] = (unsigned char)(len)/4;} while(0)
|
||||
#define hcryptMsg_KM_SetSekLen(msg,len) do {(msg)[HCRYPT_MSG_KM_OFS_KLEN] = (unsigned char)(len)/4;} while(0)
|
||||
|
||||
|
||||
#endif /* HCRYPT_MSG_H */
|
||||
|
|
|
@ -53,7 +53,7 @@ int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc,
|
|||
if (0 > (nb = crypto->cryspr->ms_decrypt(crypto->cryspr_cb, ctx, &indata, 1, NULL, NULL, NULL))) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "ms_decrypt failed\n");
|
||||
} else {
|
||||
nb = indata.len;
|
||||
nb = (int)indata.len;
|
||||
}
|
||||
} else { /* No key received yet */
|
||||
nb = 0;
|
||||
|
@ -124,9 +124,6 @@ int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc,
|
|||
|| (0 != memcmp(ctx->KMmsg_cache, in_msg, in_len))) { /* or different */
|
||||
|
||||
nbout = hcryptCtx_Rx_ParseKM(crypto, in_msg, in_len);
|
||||
//-2: unmatched shared secret
|
||||
//-1: other failures
|
||||
//0: success
|
||||
} else {
|
||||
nbout = 0;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ int hcryptCtx_SetSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_
|
|||
ctx->cfg.pwd_len = 0;
|
||||
/* KEK: Key Encrypting Key */
|
||||
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb,
|
||||
(HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false),
|
||||
((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false),
|
||||
secret->str, secret->len))) {
|
||||
HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", secret->len, iret);
|
||||
return(-1);
|
||||
|
@ -87,7 +87,7 @@ int hcryptCtx_GenSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx)
|
|||
HCRYPT_PRINTKEY(kek, kek_len, "kek");
|
||||
|
||||
/* KEK: Key Encrypting Key */
|
||||
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), kek, kek_len))) {
|
||||
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, ((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false), kek, kek_len))) {
|
||||
HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", kek_len, iret);
|
||||
return(-1);
|
||||
}
|
||||
|
|
51
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt_tx.c
vendored
51
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt_tx.c
vendored
|
@ -14,20 +14,20 @@ written by
|
|||
Haivision Systems Inc.
|
||||
|
||||
2011-06-23 (jdube)
|
||||
HaiCrypt initial implementation.
|
||||
HaiCrypt initial implementation.
|
||||
2014-03-11 (jdube)
|
||||
Adaptation for SRT.
|
||||
Adaptation for SRT.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h> /* NULL */
|
||||
#include <string.h> /* memcpy */
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdint.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <arpa/inet.h> /* htonl */
|
||||
#include <arpa/inet.h> /* htonl */
|
||||
#endif
|
||||
#include "hcrypt.h"
|
||||
|
||||
|
@ -52,28 +52,28 @@ int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_
|
|||
return(crypto->msg_info->pfx_len);
|
||||
}
|
||||
|
||||
int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout)
|
||||
int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout)
|
||||
{
|
||||
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
|
||||
hcrypt_Ctx *ctx = NULL;
|
||||
int nbout = 0;
|
||||
|
||||
if ((NULL == crypto)
|
||||
|| (NULL == (ctx = crypto->ctx))
|
||||
|| (NULL == crypto->ctx)
|
||||
|| (NULL == out_p)
|
||||
|| (NULL == out_len_p)) {
|
||||
HCRYPT_LOG(LOG_ERR, "ManageKeys: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
|
||||
HCRYPT_LOG(LOG_ERR, "ManageKeys: invalid params: crypto=%p out_p=%p out_len_p=%p\n",
|
||||
crypto, out_p, out_len_p);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Manage Key Material (refresh, announce, decommission) */
|
||||
hcryptCtx_Tx_ManageKM(crypto);
|
||||
|
||||
if (NULL == (ctx = crypto->ctx)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
|
||||
if (NULL == crypto->ctx) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "crypto context NULL after ManageKM call\n");
|
||||
return(-1);
|
||||
}
|
||||
ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE);
|
||||
ASSERT(crypto->ctx->status == HCRYPT_CTX_S_ACTIVE);
|
||||
|
||||
nbout = hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout);
|
||||
return(nbout);
|
||||
|
@ -85,27 +85,32 @@ int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc)
|
|||
hcrypt_Ctx *ctx = NULL;
|
||||
|
||||
if ((NULL == crypto)
|
||||
|| (NULL == (ctx = crypto->ctx))){
|
||||
|| (NULL == (ctx = crypto->ctx))) {
|
||||
HCRYPT_LOG(LOG_ERR, "GetKeyFlags: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
|
||||
return(-1);
|
||||
}
|
||||
return(hcryptCtx_GetKeyFlags(ctx));
|
||||
return(hcryptCtx_GetKeyFlags(crypto->ctx));
|
||||
}
|
||||
|
||||
int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
|
||||
unsigned char *in_pfx, unsigned char *in_data, size_t in_len)
|
||||
int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
|
||||
unsigned char *in_pfx, unsigned char *in_data, size_t in_len)
|
||||
{
|
||||
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
|
||||
hcrypt_Ctx *ctx = NULL;
|
||||
int nbout = 0;
|
||||
|
||||
if ((NULL == crypto)
|
||||
|| (NULL == (ctx = crypto->ctx))){
|
||||
|| (NULL == (ctx = crypto->ctx))) {
|
||||
HCRYPT_LOG(LOG_ERR, "Tx_Data: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
|
||||
return(-1);
|
||||
}
|
||||
/* Get/Set packet index */
|
||||
ctx->msg_info->indexMsg(in_pfx, ctx->MSpfx_cache);
|
||||
ctx->msg_info->indexMsg(in_pfx, ctx->MSpfx_cache);
|
||||
|
||||
if (hcryptMsg_GetKeyIndex(ctx->msg_info, in_pfx) != hcryptCtx_GetKeyIndex(ctx))
|
||||
{
|
||||
HCRYPT_LOG(LOG_ERR, "Tx_Data: Key mismatch!");
|
||||
}
|
||||
|
||||
/* Encrypt */
|
||||
{
|
||||
|
@ -124,8 +129,8 @@ int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
|
|||
return(nbout);
|
||||
}
|
||||
|
||||
int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
|
||||
unsigned char *in_msg, size_t in_len,
|
||||
int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
|
||||
unsigned char *in_msg, size_t in_len,
|
||||
void *out_p[], size_t out_len_p[], int maxout)
|
||||
{
|
||||
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
|
||||
|
@ -143,10 +148,6 @@ int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
|
|||
/* Manage Key Material (refresh, announce, decommission) */
|
||||
hcryptCtx_Tx_ManageKM(crypto);
|
||||
|
||||
if (NULL == (ctx = crypto->ctx)) {
|
||||
HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
|
||||
return(-1);
|
||||
}
|
||||
ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE);
|
||||
|
||||
nbout += hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout);
|
||||
|
|
180
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt_xpt_sta.c
vendored
180
trunk/3rdparty/srt-1-fit/haicrypt/hcrypt_xpt_sta.c
vendored
|
@ -1,180 +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.
|
||||
|
||||
2011-06-23 (jdube)
|
||||
HaiCrypt initial implementation.
|
||||
2014-03-11 (jdube)
|
||||
Adaptation for SRT.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#include <time.h> /* time() */
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <arpa/inet.h> /* htonl, ntohl */
|
||||
#endif
|
||||
#include "hcrypt.h"
|
||||
|
||||
/*
|
||||
* HaiCrypt Standalone Transport Media Stream (MS) Data Msg Prefix:
|
||||
* Cache maintained in network order
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
|
||||
* 0x00 |0|Vers | PT | Sign | resv |KF |
|
||||
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
|
||||
* 0x04 | pki |
|
||||
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
|
||||
* | payload... |
|
||||
*/
|
||||
|
||||
/*
|
||||
* HaiCrypt Standalone Transport Keying Material (KM) Msg (no prefix, use KM Msg directly):
|
||||
* Cache maintained in network order
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
|
||||
* 0x00 |0|Vers | PT | Sign | resv |
|
||||
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
|
||||
* ... .
|
||||
*/
|
||||
|
||||
#define HCRYPT_MSG_STA_HDR_SZ 4
|
||||
#define HCRYPT_MSG_STA_PKI_SZ 4
|
||||
#define HCRYPT_MSG_STA_PFX_SZ (HCRYPT_MSG_STA_HDR_SZ + HCRYPT_MSG_STA_PKI_SZ)
|
||||
|
||||
#define HCRYPT_MSG_STA_OFS_VERSION HCRYPT_MSG_KM_OFS_VERSION
|
||||
#define HCRYPT_MSG_STA_OFS_PT HCRYPT_MSG_KM_OFS_PT
|
||||
#define HCRYPT_MSG_STA_OFS_SIGN HCRYPT_MSG_KM_OFS_SIGN
|
||||
#define HCRYPT_MSG_STA_OFS_KFLGS HCRYPT_MSG_KM_OFS_KFLGS
|
||||
|
||||
#define HCRYPT_MSG_STA_OFS_PKI HCRYPT_MSG_STA_HDR_SZ
|
||||
|
||||
#define hcryptMsg_STA_GetVersion(msg) (((msg)[HCRYPT_MSG_STA_OFS_VERSION]>>4)& 0xF)
|
||||
#define hcryptMsg_STA_GetPktType(msg) (((msg)[HCRYPT_MSG_STA_OFS_PT]) & 0xF)
|
||||
#define hcryptMsg_STA_GetSign(msg) (((msg)[HCRYPT_MSG_STA_OFS_SIGN]<<8) | (msg)[HCRYPT_MSG_STA_OFS_SIGN+1])
|
||||
|
||||
static hcrypt_MsgInfo _hcMsg_STA_MsgInfo;
|
||||
|
||||
static unsigned hcryptMsg_STA_GetKeyFlags(unsigned char *msg)
|
||||
{
|
||||
return((unsigned)(msg[HCRYPT_MSG_STA_OFS_KFLGS] & HCRYPT_MSG_F_xSEK));
|
||||
}
|
||||
|
||||
static hcrypt_Pki hcryptMsg_STA_GetPki(unsigned char *msg, int nwkorder)
|
||||
{
|
||||
hcrypt_Pki pki;
|
||||
memcpy(&pki, &msg[HCRYPT_MSG_STA_OFS_PKI], sizeof(pki)); //header is in host order
|
||||
return (nwkorder ? pki : ntohl(pki));
|
||||
}
|
||||
|
||||
static void hcryptMsg_STA_SetPki(unsigned char *msg, hcrypt_Pki pki)
|
||||
{
|
||||
hcrypt_Pki nwk_pki = htonl(pki);
|
||||
memcpy(&msg[HCRYPT_MSG_STA_OFS_PKI], &nwk_pki, sizeof(nwk_pki)); //header is in host order
|
||||
}
|
||||
|
||||
static void hcryptMsg_STA_ResetCache(unsigned char *pfx_cache, unsigned pkt_type, unsigned kflgs)
|
||||
{
|
||||
pfx_cache[HCRYPT_MSG_STA_OFS_VERSION] = (unsigned char)((HCRYPT_MSG_VERSION << 4) | pkt_type); // version || PT
|
||||
pfx_cache[HCRYPT_MSG_STA_OFS_SIGN] = (unsigned char)((HCRYPT_MSG_SIGN >> 8) & 0xFF); // Haivision PnP Mfr ID
|
||||
pfx_cache[HCRYPT_MSG_STA_OFS_SIGN+1] = (unsigned char)(HCRYPT_MSG_SIGN & 0xFF);
|
||||
|
||||
switch(pkt_type) {
|
||||
case HCRYPT_MSG_PT_MS:
|
||||
pfx_cache[HCRYPT_MSG_STA_OFS_KFLGS] = (unsigned char)kflgs; //HCRYPT_MSG_F_xxx
|
||||
hcryptMsg_STA_SetPki(pfx_cache, 0);
|
||||
break;
|
||||
case HCRYPT_MSG_PT_KM:
|
||||
pfx_cache[HCRYPT_MSG_KM_OFS_KFLGS] = (unsigned char)kflgs; //HCRYPT_MSG_F_xxx
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hcryptMsg_STA_IndexMsg(unsigned char *msg, unsigned char *pfx_cache)
|
||||
{
|
||||
hcrypt_Pki pki = hcryptMsg_STA_GetPki(pfx_cache, 0); //Get in host order
|
||||
memcpy(msg, pfx_cache, HCRYPT_MSG_STA_PFX_SZ);
|
||||
hcryptMsg_SetPki(&_hcMsg_STA_MsgInfo, pfx_cache, ++pki);
|
||||
}
|
||||
|
||||
static time_t _tLastLogTime = 0;
|
||||
|
||||
static int hcryptMsg_STA_ParseMsg(unsigned char *msg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((HCRYPT_MSG_VERSION != hcryptMsg_STA_GetVersion(msg)) /* Version 1 */
|
||||
|| (HCRYPT_MSG_SIGN != hcryptMsg_STA_GetSign(msg))) { /* 'HAI' PnP Mfr ID */
|
||||
time_t tCurrentTime = time(NULL);
|
||||
// invalid data
|
||||
if ((tCurrentTime - _tLastLogTime) >= 2 || (0 == _tLastLogTime))
|
||||
{
|
||||
_tLastLogTime = tCurrentTime;
|
||||
HCRYPT_LOG(LOG_ERR, "invalid msg hdr: 0x%02x %02x%02x %02x\n",
|
||||
msg[0], msg[1], msg[2], msg[3]);
|
||||
}
|
||||
return(-1); /* Invalid packet */
|
||||
}
|
||||
rc = hcryptMsg_STA_GetPktType(msg);
|
||||
switch(rc) {
|
||||
case HCRYPT_MSG_PT_MS:
|
||||
if (hcryptMsg_HasNoSek(&_hcMsg_STA_MsgInfo, msg)
|
||||
|| hcryptMsg_HasBothSek(&_hcMsg_STA_MsgInfo, msg)) {
|
||||
HCRYPT_LOG(LOG_ERR, "invalid MS msg flgs: %02x\n",
|
||||
hcryptMsg_GetKeyIndex(&_hcMsg_STA_MsgInfo, msg));
|
||||
return(-1);
|
||||
}
|
||||
break;
|
||||
case HCRYPT_MSG_PT_KM:
|
||||
if (HCRYPT_SE_TSUDP != hcryptMsg_KM_GetSE(msg)) {
|
||||
HCRYPT_LOG(LOG_ERR, "invalid KM msg SE: %d\n",
|
||||
hcryptMsg_KM_GetSE(msg));
|
||||
} else if (hcryptMsg_KM_HasNoSek(msg)) {
|
||||
HCRYPT_LOG(LOG_ERR, "invalid KM msg flgs: %02x\n",
|
||||
hcryptMsg_KM_GetKeyIndex(msg));
|
||||
return(-1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
HCRYPT_LOG(LOG_ERR, "invalid pkt type: %d\n", rc);
|
||||
rc = 0; /* unknown packet type */
|
||||
break;
|
||||
}
|
||||
return(rc); /* -1: error, 0: unknown: >0: PT */
|
||||
}
|
||||
|
||||
static hcrypt_MsgInfo _hcMsg_STA_MsgInfo;
|
||||
|
||||
hcrypt_MsgInfo *hcryptMsg_STA_MsgInfo(void)
|
||||
{
|
||||
_hcMsg_STA_MsgInfo.hdr_len = HCRYPT_MSG_STA_HDR_SZ;
|
||||
_hcMsg_STA_MsgInfo.pfx_len = HCRYPT_MSG_STA_PFX_SZ;
|
||||
_hcMsg_STA_MsgInfo.getKeyFlags = hcryptMsg_STA_GetKeyFlags;
|
||||
_hcMsg_STA_MsgInfo.getPki = hcryptMsg_STA_GetPki;
|
||||
_hcMsg_STA_MsgInfo.setPki = hcryptMsg_STA_SetPki;
|
||||
_hcMsg_STA_MsgInfo.resetCache = hcryptMsg_STA_ResetCache;
|
||||
_hcMsg_STA_MsgInfo.indexMsg = hcryptMsg_STA_IndexMsg;
|
||||
_hcMsg_STA_MsgInfo.parseMsg = hcryptMsg_STA_ParseMsg;
|
||||
|
||||
return(&_hcMsg_STA_MsgInfo);
|
||||
}
|
||||
|
62
trunk/3rdparty/srt-1-fit/scripts/CheckCXXAtomic.cmake
vendored
Normal file
62
trunk/3rdparty/srt-1-fit/scripts/CheckCXXAtomic.cmake
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
# Check for c++11 std::atomic.
|
||||
#
|
||||
# Sets:
|
||||
# HAVE_CXX_ATOMIC
|
||||
# HAVE_CXX_ATOMIC_STATIC
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
|
||||
function(CheckCXXAtomic)
|
||||
|
||||
unset(HAVE_CXX_ATOMIC CACHE)
|
||||
unset(HAVE_CXX_ATOMIC_STATIC CACHE)
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
|
||||
set(CheckCXXAtomic_CODE
|
||||
"
|
||||
#include<cstdint>
|
||||
#include<atomic>
|
||||
int main(void)
|
||||
{
|
||||
std::atomic<std::ptrdiff_t> x(0);
|
||||
std::atomic<std::intmax_t> y(0);
|
||||
return x + y;
|
||||
}
|
||||
")
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
|
||||
check_cxx_source_compiles(
|
||||
"${CheckCXXAtomic_CODE}"
|
||||
HAVE_CXX_ATOMIC)
|
||||
|
||||
if(HAVE_CXX_ATOMIC)
|
||||
# CMAKE_REQUIRED_LINK_OPTIONS was introduced in CMake 3.14.
|
||||
if(CMAKE_VERSION VERSION_LESS "3.14")
|
||||
set(CMAKE_REQUIRED_LINK_OPTIONS "-static")
|
||||
else()
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -static")
|
||||
endif()
|
||||
check_cxx_source_compiles(
|
||||
"${CheckCXXAtomic_CODE}"
|
||||
HAVE_CXX_ATOMIC_STATIC)
|
||||
endif()
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
|
||||
endfunction(CheckCXXAtomic)
|
57
trunk/3rdparty/srt-1-fit/scripts/CheckCXXStdPutTime.cmake
vendored
Normal file
57
trunk/3rdparty/srt-1-fit/scripts/CheckCXXStdPutTime.cmake
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
# SRT - Secure, Reliable, Transport Copyright (c) 2022 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/.
|
||||
#
|
||||
|
||||
# Check for C++11 std::put_time().
|
||||
#
|
||||
# Sets:
|
||||
# HAVE_CXX_STD_PUT_TIME
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
function(CheckCXXStdPutTime)
|
||||
|
||||
unset(HAVE_CXX_STD_PUT_TIME CACHE)
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) # CMake 3.6
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
|
||||
set(CheckCXXStdPutTime_CODE
|
||||
"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
int main(void)
|
||||
{
|
||||
const int result = 0;
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
std::cout
|
||||
<< std::put_time(&tm, \"%FT%T\")
|
||||
<< std::setfill('0')
|
||||
<< std::setw(6)
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
# NOTE: Should we set -std or use the current compiler configuration.
|
||||
# It seems that the top level build does not track the compiler
|
||||
# in a consistent manner. So Maybe we need this?
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
|
||||
# Check that the compiler can build the std::put_time() example:
|
||||
message(STATUS "Checking for C++ 'std::put_time()':")
|
||||
check_cxx_source_compiles(
|
||||
"${CheckCXXStdPutTime_CODE}"
|
||||
HAVE_CXX_STD_PUT_TIME)
|
||||
|
||||
endfunction(CheckCXXStdPutTime)
|
113
trunk/3rdparty/srt-1-fit/scripts/CheckGCCAtomicIntrinsics.cmake
vendored
Normal file
113
trunk/3rdparty/srt-1-fit/scripts/CheckGCCAtomicIntrinsics.cmake
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
# Check for GCC Atomic Intrinsics and whether libatomic is required.
|
||||
#
|
||||
# Sets:
|
||||
# HAVE_LIBATOMIC
|
||||
# HAVE_LIBATOMIC_COMPILES
|
||||
# HAVE_LIBATOMIC_COMPILES_STATIC
|
||||
# HAVE_GCCATOMIC_INTRINSICS
|
||||
# HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC
|
||||
#
|
||||
# See
|
||||
# https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
|
||||
# https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
|
||||
function(CheckGCCAtomicIntrinsics)
|
||||
|
||||
unset(HAVE_LIBATOMIC CACHE)
|
||||
unset(HAVE_LIBATOMIC_COMPILES CACHE)
|
||||
unset(HAVE_LIBATOMIC_COMPILES_STATIC CACHE)
|
||||
unset(HAVE_GCCATOMIC_INTRINSICS CACHE)
|
||||
unset(HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC CACHE)
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) # CMake 3.6
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
|
||||
# Check for existence of libatomic and whether this symbol is present.
|
||||
check_library_exists(atomic __atomic_fetch_add_8 "" HAVE_LIBATOMIC)
|
||||
|
||||
set(CheckLibAtomicCompiles_CODE
|
||||
"
|
||||
int main(void)
|
||||
{
|
||||
const int result = 0;
|
||||
return result;
|
||||
}
|
||||
")
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
|
||||
# Check that the compiler can build a simple application and link with
|
||||
# libatomic.
|
||||
check_c_source_compiles("${CheckLibAtomicCompiles_CODE}"
|
||||
HAVE_LIBATOMIC_COMPILES)
|
||||
if(NOT HAVE_LIBATOMIC_COMPILES)
|
||||
set(HAVE_LIBATOMIC
|
||||
0
|
||||
CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
if(HAVE_LIBATOMIC AND HAVE_LIBATOMIC_COMPILES)
|
||||
# CMAKE_REQUIRED_LINK_OPTIONS was introduced in CMake 3.14.
|
||||
if(CMAKE_VERSION VERSION_LESS "3.14")
|
||||
set(CMAKE_REQUIRED_LINK_OPTIONS "-static")
|
||||
else()
|
||||
set(CMAKE_REQUIRED_FLAGS "-static")
|
||||
endif()
|
||||
# Check that the compiler can build a simple application and statically link
|
||||
# with libatomic.
|
||||
check_c_source_compiles("${CheckLibAtomicCompiles_CODE}"
|
||||
HAVE_LIBATOMIC_COMPILES_STATIC)
|
||||
else()
|
||||
set(HAVE_LIBATOMIC_COMPILES_STATIC
|
||||
0
|
||||
CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
|
||||
set(CheckGCCAtomicIntrinsics_CODE
|
||||
"
|
||||
#include<stddef.h>
|
||||
#include<stdint.h>
|
||||
int main(void)
|
||||
{
|
||||
ptrdiff_t x = 0;
|
||||
intmax_t y = 0;
|
||||
__atomic_add_fetch(&x, 1, __ATOMIC_SEQ_CST);
|
||||
__atomic_add_fetch(&y, 1, __ATOMIC_SEQ_CST);
|
||||
return __atomic_sub_fetch(&x, 1, __ATOMIC_SEQ_CST)
|
||||
+ __atomic_sub_fetch(&y, 1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
")
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) # CMake 3.6
|
||||
check_c_source_compiles("${CheckGCCAtomicIntrinsics_CODE}"
|
||||
HAVE_GCCATOMIC_INTRINSICS)
|
||||
|
||||
if(NOT HAVE_GCCATOMIC_INTRINSICS AND HAVE_LIBATOMIC)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_c_source_compiles("${CheckGCCAtomicIntrinsics_CODE}"
|
||||
HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC)
|
||||
if(HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC)
|
||||
set(HAVE_GCCATOMIC_INTRINSICS
|
||||
1
|
||||
CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endfunction(CheckGCCAtomicIntrinsics)
|
|
@ -111,5 +111,5 @@ endif()
|
|||
|
||||
# Now we've accounted for the 3-vs-1 library case:
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libmbedtls DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS)
|
||||
find_package_handle_standard_args(MbedTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS)
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS)
|
||||
|
|
73
trunk/3rdparty/srt-1-fit/scripts/FindPThreadGetSetName.cmake
vendored
Normal file
73
trunk/3rdparty/srt-1-fit/scripts/FindPThreadGetSetName.cmake
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
# Check for pthread_getname_np(3) and pthread_setname_np(3)
|
||||
# used in srtcore/threadname.h.
|
||||
#
|
||||
# Some BSD distros need to include <pthread_np.h> for pthread_getname_np().
|
||||
#
|
||||
# TODO: Some BSD distros have pthread_get_name_np() and pthread_set_name_np()
|
||||
# instead of pthread_getname_np() and pthread_setname_np().
|
||||
#
|
||||
# Sets:
|
||||
# HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H
|
||||
# HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H
|
||||
# HAVE_PTHREAD_GETNAME_NP
|
||||
# HAVE_PTHREAD_SETNAME_NP
|
||||
# Sets as appropriate:
|
||||
# add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1)
|
||||
# add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1)
|
||||
# add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1)
|
||||
# add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
|
||||
function(FindPThreadGetSetName)
|
||||
|
||||
unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H CACHE)
|
||||
unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H CACHE)
|
||||
unset(HAVE_PTHREAD_GETNAME_NP CACHE)
|
||||
unset(HAVE_PTHREAD_SETNAME_NP CACHE)
|
||||
|
||||
set(CMAKE_REQUIRED_DEFINITIONS
|
||||
-D_GNU_SOURCE -D_DARWIN_C_SOURCE -D_POSIX_SOURCE=1)
|
||||
set(CMAKE_REQUIRED_FLAGS "-pthread")
|
||||
|
||||
message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread_np.h':")
|
||||
check_symbol_exists(
|
||||
pthread_getname_np "pthread_np.h" HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H)
|
||||
if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H)
|
||||
add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1)
|
||||
endif()
|
||||
check_symbol_exists(
|
||||
pthread_setname_np "pthread_np.h" HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H)
|
||||
if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H)
|
||||
add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1)
|
||||
endif()
|
||||
|
||||
message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread.h':")
|
||||
check_symbol_exists(pthread_getname_np "pthread.h" HAVE_PTHREAD_GETNAME_NP)
|
||||
if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H)
|
||||
set(HAVE_PTHREAD_GETNAME_NP 1 CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
check_symbol_exists(pthread_setname_np "pthread.h" HAVE_PTHREAD_SETNAME_NP)
|
||||
if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H)
|
||||
set(HAVE_PTHREAD_SETNAME_NP 1 CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
if (HAVE_PTHREAD_GETNAME_NP)
|
||||
add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1)
|
||||
endif()
|
||||
if (HAVE_PTHREAD_SETNAME_NP)
|
||||
add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1)
|
||||
endif()
|
||||
|
||||
unset(CMAKE_REQUIRED_DEFINITIONS)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
endfunction(FindPThreadGetSetName)
|
192
trunk/3rdparty/srt-1-fit/scripts/ShowProjectConfig.cmake
vendored
Normal file
192
trunk/3rdparty/srt-1-fit/scripts/ShowProjectConfig.cmake
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
function(ShowProjectConfig)
|
||||
|
||||
set(__ssl_configuration)
|
||||
if (SSL_FOUND OR SSL_LIBRARIES)
|
||||
set(__ssl_configuration
|
||||
" SSL Configuration:
|
||||
SSL_FOUND=${SSL_FOUND}
|
||||
SSL_INCLUDE_DIRS=${SSL_INCLUDE_DIRS}
|
||||
SSL_LIBRARIES=${SSL_LIBRARIES}
|
||||
SSL_VERSION=${SSL_VERSION}\n")
|
||||
endif()
|
||||
|
||||
set(static_property_link_libraries)
|
||||
if (srt_libspec_static)
|
||||
get_target_property(
|
||||
static_property_link_libraries
|
||||
${TARGET_srt}_static
|
||||
LINK_LIBRARIES)
|
||||
endif()
|
||||
set(shared_property_link_libraries)
|
||||
if (srt_libspec_shared)
|
||||
get_target_property(
|
||||
shared_property_link_libraries
|
||||
${TARGET_srt}_shared
|
||||
LINK_LIBRARIES)
|
||||
endif()
|
||||
|
||||
# See https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#id13
|
||||
set(__more_tc1_config)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
set(__more_tc1_config
|
||||
" CMAKE_SYSROOT: ${CMAKE_SYSROOT}\n")
|
||||
endif()
|
||||
|
||||
# See https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#id13
|
||||
set(__more_tc2_config)
|
||||
if (APPLE)
|
||||
set(__more_tc2_config
|
||||
" CMAKE_INSTALL_NAME_TOOL: ${CMAKE_INSTALL_NAME_TOOL}
|
||||
CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}
|
||||
CMAKE_OSX_ARCHITECTURES: ${CMAKE_OSX_ARCHITECTURES}
|
||||
CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}
|
||||
CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}\n")
|
||||
elseif (ANDROID)
|
||||
set(__more_tc2_config
|
||||
" CMAKE_ANDROID_NDK: ${CMAKE_ANDROID_NDK}
|
||||
CMAKE_ANDROID_STANDALONE_TOOLCHAIN: ${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}
|
||||
CMAKE_ANDROID_API: ${CMAKE_ANDROID_API}
|
||||
CMAKE_ANDROID_ARCH_ABI: ${CMAKE_ANDROID_ARCH_ABI}
|
||||
CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION: ${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}
|
||||
CMAKE_ANDROID_STL_TYPE: ${CMAKE_ANDROID_STL_TYPE}\n")
|
||||
endif()
|
||||
|
||||
message(STATUS
|
||||
"\n"
|
||||
"========================================================================\n"
|
||||
"= Project Configuration:\n"
|
||||
"========================================================================\n"
|
||||
" SRT Version:\n"
|
||||
" SRT_VERSION: ${SRT_VERSION}\n"
|
||||
" SRT_VERSION_BUILD: ${SRT_VERSION_BUILD}\n"
|
||||
" CMake Configuration:\n"
|
||||
" CMAKE_VERSION: ${CMAKE_VERSION}\n"
|
||||
" CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n"
|
||||
" CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n"
|
||||
" Target Configuration:\n"
|
||||
" CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}\n"
|
||||
" CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}\n"
|
||||
" CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}\n"
|
||||
" CMAKE_SIZEOF_VOID_P: ${CMAKE_SIZEOF_VOID_P}\n"
|
||||
" DARWIN: ${DARWIN}\n"
|
||||
" LINUX: ${LINUX}\n"
|
||||
" BSD: ${BSD}\n"
|
||||
" MICROSOFT: ${MICROSOFT}\n"
|
||||
" GNU: ${GNU}\n"
|
||||
" ANDROID: ${ANDROID}\n"
|
||||
" SUNOS: ${SUNOS}\n"
|
||||
" POSIX: ${POSIX}\n"
|
||||
" SYMLINKABLE: ${SYMLINKABLE}\n"
|
||||
" APPLE: ${APPLE}\n"
|
||||
" UNIX: ${UNIX}\n"
|
||||
" WIN32: ${WIN32}\n"
|
||||
" MINGW: ${MINGW}\n"
|
||||
" CYGWIN: ${CYGWIN}\n"
|
||||
" CYGWIN_USE_POSIX: ${CYGWIN_USE_POSIX}\n"
|
||||
" Toolchain Configuration:\n"
|
||||
" CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}\n"
|
||||
" CMAKE_CROSSCOMPILING: ${CMAKE_CROSSCOMPILING}\n"
|
||||
"${__more_tc1_config}"
|
||||
" CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}\n"
|
||||
" CMAKE_C_COMPILER_VERSION: ${CMAKE_C_COMPILER_VERSION}\n"
|
||||
" CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}\n"
|
||||
" CMAKE_C_FLAGS: '${CMAKE_C_FLAGS}'\n"
|
||||
" CMAKE_C_COMPILE_FEATURES: ${CMAKE_C_COMPILE_FEATURES}\n"
|
||||
" CMAKE_C_STANDARD: ${CMAKE_CXX_STANDARD}\n"
|
||||
" CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}\n"
|
||||
" CMAKE_CXX_COMPILER_VERSION: ${CMAKE_CXX_COMPILER_VERSION}\n"
|
||||
" CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}\n"
|
||||
" CMAKE_CXX_FLAGS: '${CMAKE_CXX_FLAGS}'\n"
|
||||
" CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}\n"
|
||||
" CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}\n"
|
||||
" CMAKE_LINKER: ${CMAKE_LINKER}\n"
|
||||
#" CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}\n"
|
||||
#" CMAKE_EXE_LINKER_FLAGS_INIT: ${CMAKE_EXE_LINKER_FLAGS_INIT}\n"
|
||||
#" CMAKE_MODULE_LINKER_FLAGS: ${CMAKE_MODULE_LINKER_FLAGS}\n"
|
||||
#" CMAKE_MODULE_LINKER_FLAGS_INIT: ${CMAKE_MODULE_LINKER_FLAGS_INIT}\n"
|
||||
#" CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}\n"
|
||||
#" CMAKE_SHARED_LINKER_FLAGS_INIT: ${CMAKE_SHARED_LINKER_FLAGS_INIT}\n"
|
||||
#" CMAKE_STATIC_LINKER_FLAGS: ${CMAKE_STATIC_LINKER_FLAGS}\n"
|
||||
#" CMAKE_STATIC_LINKER_FLAGS_INIT: ${CMAKE_STATIC_LINKER_FLAGS_INIT}\n"
|
||||
" CMAKE_NM: ${CMAKE_NM}\n"
|
||||
" CMAKE_AR: ${CMAKE_AR}\n"
|
||||
" CMAKE_RANLIB: ${CMAKE_RANLIB}\n"
|
||||
"${__more_tc2_config}"
|
||||
" HAVE_COMPILER_GNU_COMPAT: ${HAVE_COMPILER_GNU_COMPAT}\n"
|
||||
" CMAKE_THREAD_LIBS: ${CMAKE_THREAD_LIBS}\n"
|
||||
" CMAKE_THREAD_LIBS_INIT: ${CMAKE_THREAD_LIBS_INIT}\n"
|
||||
" ENABLE_THREAD_CHECK: ${ENABLE_THREAD_CHECK}\n"
|
||||
" USE_CXX_STD_APP: ${USE_CXX_STD_APP}\n"
|
||||
" USE_CXX_STD_LIB: ${USE_CXX_STD_LIB}\n"
|
||||
" STDCXX: ${STDCXX}\n"
|
||||
" USE_CXX_STD: ${USE_CXX_STD}\n"
|
||||
" HAVE_CLOCK_GETTIME_IN: ${HAVE_CLOCK_GETTIME_IN}\n"
|
||||
" HAVE_CLOCK_GETTIME_LIBRT: ${HAVE_CLOCK_GETTIME_LIBRT}\n"
|
||||
" HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H: ${HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H}\n"
|
||||
" HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H: ${HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H}\n"
|
||||
" HAVE_PTHREAD_GETNAME_NP: ${HAVE_PTHREAD_GETNAME_NP}\n"
|
||||
" HAVE_PTHREAD_SETNAME_NP: ${HAVE_PTHREAD_SETNAME_NP}\n"
|
||||
" HAVE_LIBATOMIC: ${HAVE_LIBATOMIC}\n"
|
||||
" HAVE_LIBATOMIC_COMPILES: ${HAVE_LIBATOMIC_COMPILES}\n"
|
||||
" HAVE_LIBATOMIC_COMPILES_STATIC: ${HAVE_LIBATOMIC_COMPILES_STATIC}\n"
|
||||
" HAVE_GCCATOMIC_INTRINSICS: ${HAVE_GCCATOMIC_INTRINSICS}\n"
|
||||
" HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC: ${HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC}\n"
|
||||
" HAVE_CXX_ATOMIC: ${HAVE_CXX_ATOMIC}\n"
|
||||
" HAVE_CXX_ATOMIC_STATIC: ${HAVE_CXX_ATOMIC_STATIC}\n"
|
||||
" HAVE_CXX_STD_PUT_TIME: ${HAVE_CXX_STD_PUT_TIME}\n"
|
||||
" Project Configuration:\n"
|
||||
" ENABLE_DEBUG: ${ENABLE_DEBUG}\n"
|
||||
" ENABLE_CXX11: ${ENABLE_CXX11}\n"
|
||||
" ENABLE_APPS: ${ENABLE_APPS}\n"
|
||||
" ENABLE_EXAMPLES: ${ENABLE_EXAMPLES}\n"
|
||||
" ENABLE_BONDING: ${ENABLE_BONDING}\n"
|
||||
" ENABLE_TESTING: ${ENABLE_TESTING}\n"
|
||||
" ENABLE_PROFILE: ${ENABLE_PROFILE}\n"
|
||||
" ENABLE_LOGGING: ${ENABLE_LOGGING}\n"
|
||||
" ENABLE_HEAVY_LOGGING: ${ENABLE_HEAVY_LOGGING}\n"
|
||||
" ENABLE_HAICRYPT_LOGGING: ${ENABLE_HAICRYPT_LOGGING}\n"
|
||||
" ENABLE_SHARED: ${ENABLE_SHARED}\n"
|
||||
" ENABLE_STATIC: ${ENABLE_STATIC}\n"
|
||||
" ENABLE_RELATIVE_LIBPATH: ${ENABLE_RELATIVE_LIBPATH}\n"
|
||||
" ENABLE_GETNAMEINFO: ${ENABLE_GETNAMEINFO}\n"
|
||||
" ENABLE_UNITTESTS: ${ENABLE_UNITTESTS}\n"
|
||||
" ENABLE_ENCRYPTION: ${ENABLE_ENCRYPTION}\n"
|
||||
" ENABLE_CXX_DEPS: ${ENABLE_CXX_DEPS}\n"
|
||||
" USE_STATIC_LIBSTDCXX: ${USE_STATIC_LIBSTDCXX}\n"
|
||||
" ENABLE_INET_PTON: ${ENABLE_INET_PTON}\n"
|
||||
" ENABLE_CODE_COVERAGE: ${ENABLE_CODE_COVERAGE}\n"
|
||||
" ENABLE_MONOTONIC_CLOCK: ${ENABLE_MONOTONIC_CLOCK}\n"
|
||||
" ENABLE_STDCXX_SYNC: ${ENABLE_STDCXX_SYNC}\n"
|
||||
" USE_OPENSSL_PC: ${USE_OPENSSL_PC}\n"
|
||||
" OPENSSL_USE_STATIC_LIBS: ${OPENSSL_USE_STATIC_LIBS}\n"
|
||||
" USE_BUSY_WAITING: ${USE_BUSY_WAITING}\n"
|
||||
" USE_GNUSTL: ${USE_GNUSTL}\n"
|
||||
" ENABLE_SOCK_CLOEXEC: ${ENABLE_SOCK_CLOEXEC}\n"
|
||||
" ENABLE_SHOW_PROJECT_CONFIG: ${ENABLE_SHOW_PROJECT_CONFIG}\n"
|
||||
" ENABLE_CLANG_TSA: ${ENABLE_CLANG_TSA}\n"
|
||||
" ATOMIC_USE_SRT_SYNC_MUTEX: ${ATOMIC_USE_SRT_SYNC_MUTEX}\n"
|
||||
" Constructed Configuration:\n"
|
||||
" DISABLE_CXX11: ${DISABLE_CXX11}\n"
|
||||
" HAVE_INET_PTON: ${HAVE_INET_PTON}\n"
|
||||
" PTHREAD_LIBRARY: ${PTHREAD_LIBRARY}\n"
|
||||
" USE_ENCLIB: ${USE_ENCLIB}\n"
|
||||
"${__ssl_configuration}"
|
||||
" TARGET_srt: ${TARGET_srt}\n"
|
||||
" srt_libspec_static: ${srt_libspec_static}\n"
|
||||
" srt_libspec_shared: ${srt_libspec_shared}\n"
|
||||
" SRT_LIBS_PRIVATE: ${SRT_LIBS_PRIVATE}\n"
|
||||
" Target Link Libraries:\n"
|
||||
" Static: ${static_property_link_libraries}\n"
|
||||
" Shared: ${shared_property_link_libraries}\n"
|
||||
"========================================================================\n"
|
||||
)
|
||||
|
||||
endfunction(ShowProjectConfig)
|
3
trunk/3rdparty/srt-1-fit/scripts/build-android/README.md
vendored
Normal file
3
trunk/3rdparty/srt-1-fit/scripts/build-android/README.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
## Scripts for building SRT for Android
|
||||
|
||||
See [Building SRT for Android](../../docs/build/build-android.md) for the instructions.
|
111
trunk/3rdparty/srt-1-fit/scripts/build-android/build-android
vendored
Executable file
111
trunk/3rdparty/srt-1-fit/scripts/build-android/build-android
vendored
Executable file
|
@ -0,0 +1,111 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo_help()
|
||||
{
|
||||
echo "Usage: $0 [options...]"
|
||||
echo " -n NDK root path for the build"
|
||||
echo " -a Target API level"
|
||||
echo " -t Space-separated list of target architectures"
|
||||
echo " Android supports the following architectures: armeabi-v7a arm64-v8a x86 x86_64"
|
||||
echo " -e Encryption library to be used. Possible options: openssl (default) mbedtls"
|
||||
echo " -o OpenSSL version. E.g. 1.1.1l"
|
||||
echo " -m Mbed TLS version. E.g. v2.26.0"
|
||||
echo
|
||||
echo "Example: ./build-android -n /home/username/Android/Sdk/ndk/23.0.7599858 -a 28 -t \"arm64-v8a x86_64\""
|
||||
echo
|
||||
}
|
||||
|
||||
# Init optional command line vars
|
||||
NDK_ROOT=""
|
||||
API_LEVEL=28
|
||||
BUILD_TARGETS="armeabi-v7a arm64-v8a x86 x86_64"
|
||||
OPENSSL_VERSION=1.1.1l
|
||||
ENC_LIB=openssl
|
||||
MBEDTLS_VERSION=v2.26.0
|
||||
|
||||
while getopts n:a:t:o:s:e:m: option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
n) NDK_ROOT=${OPTARG};;
|
||||
a) API_LEVEL=${OPTARG};;
|
||||
t) BUILD_TARGETS=${OPTARG};;
|
||||
o) OPENSSL_VERSION=${OPTARG};;
|
||||
s) SRT_VERSION=${OPTARG};;
|
||||
e) ENC_LIB=${OPTARG};;
|
||||
m) MBEDTLS_VERSION=${OPTARG};;
|
||||
*) twentytwo=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
echo_help
|
||||
|
||||
if [ -z "$NDK_ROOT" ] ; then
|
||||
echo "NDK directory not set."
|
||||
exit 128
|
||||
else
|
||||
if [ ! -d "$NDK_ROOT" ]; then
|
||||
echo "NDK directory does not exist: $NDK_ROOT"
|
||||
exit 128
|
||||
fi
|
||||
fi
|
||||
|
||||
SCRIPT_DIR=$(pwd)
|
||||
HOST_TAG='unknown'
|
||||
unamestr=$(uname -s)
|
||||
if [ "$unamestr" = 'Linux' ]; then
|
||||
HOST_TAG='linux-x86_64'
|
||||
elif [ "$unamestr" = 'Darwin' ]; then
|
||||
if [ $(uname -p) = 'arm' ]; then
|
||||
echo "NDK does not currently support ARM64"
|
||||
exit 128
|
||||
else
|
||||
HOST_TAG='darwin-x86_64'
|
||||
fi
|
||||
fi
|
||||
|
||||
# Write files relative to current location
|
||||
BASE_DIR=$(pwd)
|
||||
case "${BASE_DIR}" in
|
||||
*\ * )
|
||||
echo "Your path contains whitespaces, which is not supported by 'make install'."
|
||||
exit 128
|
||||
;;
|
||||
esac
|
||||
cd "${BASE_DIR}"
|
||||
|
||||
if [ $ENC_LIB = 'openssl' ]; then
|
||||
echo "Building OpenSSL $OPENSSL_VERSION"
|
||||
$SCRIPT_DIR/mkssl -n $NDK_ROOT -a $API_LEVEL -t "$BUILD_TARGETS" -o $OPENSSL_VERSION -d $BASE_DIR -h $HOST_TAG
|
||||
elif [ $ENC_LIB = 'mbedtls' ]; then
|
||||
if [ ! -d $BASE_DIR/mbedtls ]; then
|
||||
git clone https://github.com/ARMmbed/mbedtls mbedtls
|
||||
if [ ! -z "$MBEDTLS_VERSION" ]; then
|
||||
git -C $BASE_DIR/mbedtls checkout $MBEDTLS_VERSION
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Unknown encryption library. Possible options: openssl mbedtls"
|
||||
exit 128
|
||||
fi
|
||||
|
||||
# Build working copy of srt repository
|
||||
REPO_DIR="../.."
|
||||
|
||||
for build_target in $BUILD_TARGETS; do
|
||||
LIB_DIR=$BASE_DIR/$build_target/lib
|
||||
JNI_DIR=$BASE_DIR/prebuilt/$build_target
|
||||
|
||||
mkdir -p $JNI_DIR
|
||||
|
||||
if [ $ENC_LIB = 'mbedtls' ]; then
|
||||
$SCRIPT_DIR/mkmbedtls -n $NDK_ROOT -a $API_LEVEL -t $build_target -s $BASE_DIR/mbedtls -i $BASE_DIR/$build_target
|
||||
cp $LIB_DIR/libmbedcrypto.so $JNI_DIR/libmbedcrypto.so
|
||||
cp $LIB_DIR/libmbedtls.so $JNI_DIR/libmbedtls.so
|
||||
cp $LIB_DIR/libmbedx509.so $JNI_DIR/libmbedx509.so
|
||||
fi
|
||||
|
||||
git -C $REPO_DIR clean -fd -e scripts
|
||||
$SCRIPT_DIR/mksrt -n $NDK_ROOT -a $API_LEVEL -t $build_target -e $ENC_LIB -s $REPO_DIR -i $BASE_DIR/$build_target
|
||||
cp $LIB_DIR/libsrt.so $JNI_DIR/libsrt.so
|
||||
done
|
27
trunk/3rdparty/srt-1-fit/scripts/build-android/mkmbedtls
vendored
Executable file
27
trunk/3rdparty/srt-1-fit/scripts/build-android/mkmbedtls
vendored
Executable file
|
@ -0,0 +1,27 @@
|
|||
#!/bin/sh
|
||||
|
||||
while getopts s:i:t:n:a: option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
s) SRC_DIR=${OPTARG};;
|
||||
i) INSTALL_DIR=${OPTARG};;
|
||||
t) ARCH_ABI=${OPTARG};;
|
||||
n) NDK_ROOT=${OPTARG};;
|
||||
a) API_LEVEL=${OPTARG};;
|
||||
*) twentytwo=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
BUILD_DIR=/tmp/mbedtls_android_build
|
||||
rm -rf $BUILD_DIR
|
||||
mkdir $BUILD_DIR
|
||||
cd $BUILD_DIR
|
||||
cmake -DENABLE_TESTING=Off -DUSE_SHARED_MBEDTLS_LIBRARY=On \
|
||||
-DCMAKE_PREFIX_PATH=$INSTALL_DIR -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DCMAKE_ANDROID_NDK=$NDK_ROOT \
|
||||
-DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=$API_LEVEL -DCMAKE_ANDROID_ARCH_ABI=$ARCH_ABI \
|
||||
-DCMAKE_C_FLAGS="-fPIC" -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--build-id" \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo $SRC_DIR
|
||||
cmake --build .
|
||||
cmake --install .
|
32
trunk/3rdparty/srt-1-fit/scripts/build-android/mksrt
vendored
Executable file
32
trunk/3rdparty/srt-1-fit/scripts/build-android/mksrt
vendored
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
|
||||
while getopts s:i:t:n:a:e: option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
s) SRC_DIR=${OPTARG};;
|
||||
i) INSTALL_DIR=${OPTARG};;
|
||||
t) ARCH_ABI=${OPTARG};;
|
||||
n) NDK_ROOT=${OPTARG};;
|
||||
a) API_LEVEL=${OPTARG};;
|
||||
e) ENC_LIB=${OPTARG};;
|
||||
*) twentytwo=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
cd $SRC_DIR
|
||||
./configure --use-enclib=$ENC_LIB \
|
||||
--use-openssl-pc=OFF \
|
||||
--OPENSSL_INCLUDE_DIR=$INSTALL_DIR/include \
|
||||
--OPENSSL_CRYPTO_LIBRARY=$INSTALL_DIR/lib/libcrypto.a --OPENSSL_SSL_LIBRARY=$INSTALL_DIR/lib/libssl.a \
|
||||
--STATIC_MBEDTLS=FALSE \
|
||||
--MBEDTLS_INCLUDE_DIR=$INSTALL_DIR/include --MBEDTLS_INCLUDE_DIRS=$INSTALL_DIR/include \
|
||||
--MBEDTLS_LIBRARIES=$INSTALL_DIR/lib/libmbedtls.so \
|
||||
--CMAKE_PREFIX_PATH=$INSTALL_DIR --CMAKE_INSTALL_PREFIX=$INSTALL_DIR --CMAKE_ANDROID_NDK=$NDK_ROOT \
|
||||
--CMAKE_SYSTEM_NAME=Android --CMAKE_SYSTEM_VERSION=$API_LEVEL --CMAKE_ANDROID_ARCH_ABI=$ARCH_ABI \
|
||||
--CMAKE_C_FLAGS="-fPIC" --CMAKE_SHARED_LINKER_FLAGS="-Wl,--build-id" \
|
||||
--enable-c++11 --enable-stdcxx-sync \
|
||||
--enable-debug=2 --enable-logging=0 --enable-heavy-logging=0 --enable-apps=0
|
||||
make
|
||||
make install
|
85
trunk/3rdparty/srt-1-fit/scripts/build-android/mkssl
vendored
Executable file
85
trunk/3rdparty/srt-1-fit/scripts/build-android/mkssl
vendored
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/bin/sh
|
||||
|
||||
while getopts n:o:a:t:d:h: option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
n) ANDROID_NDK=${OPTARG};;
|
||||
o) OPENSSL_VERSION=${OPTARG};;
|
||||
a) API_LEVEL=${OPTARG};;
|
||||
t) BUILD_TARGETS=${OPTARG};;
|
||||
d) OUT_DIR=${OPTARG};;
|
||||
h) HOST_TAG=${OPTARG};;
|
||||
*) twentytwo=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
BUILD_DIR=/tmp/openssl_android_build
|
||||
|
||||
if [ ! -d openssl-${OPENSSL_VERSION} ]
|
||||
then
|
||||
if [ ! -f openssl-${OPENSSL_VERSION}.tar.gz ]
|
||||
then
|
||||
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz || exit 128
|
||||
fi
|
||||
tar xzf openssl-${OPENSSL_VERSION}.tar.gz || exit 128
|
||||
fi
|
||||
|
||||
cd openssl-${OPENSSL_VERSION} || exit 128
|
||||
|
||||
|
||||
##### export ndk directory. Required by openssl-build-scripts #####
|
||||
case ${OPENSSL_VERSION} in
|
||||
1.1.1*)
|
||||
export ANDROID_NDK_HOME=$ANDROID_NDK
|
||||
;;
|
||||
*)
|
||||
export ANDROID_NDK_ROOT=$ANDROID_NDK
|
||||
;;
|
||||
esac
|
||||
|
||||
export PATH=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin:$PATH
|
||||
|
||||
##### build-function #####
|
||||
build_the_thing() {
|
||||
make clean
|
||||
./Configure $SSL_TARGET -D__ANDROID_API__=$API_LEVEL && \
|
||||
make SHLIB_EXT=.so && \
|
||||
make install SHLIB_EXT=.so DESTDIR=$DESTDIR || exit 128
|
||||
}
|
||||
|
||||
##### set variables according to build-tagret #####
|
||||
for build_target in $BUILD_TARGETS
|
||||
do
|
||||
case $build_target in
|
||||
armeabi-v7a)
|
||||
DESTDIR="$BUILD_DIR/armeabi-v7a"
|
||||
SSL_TARGET="android-arm"
|
||||
;;
|
||||
x86)
|
||||
DESTDIR="$BUILD_DIR/x86"
|
||||
SSL_TARGET="android-x86"
|
||||
;;
|
||||
x86_64)
|
||||
DESTDIR="$BUILD_DIR/x86_64"
|
||||
SSL_TARGET="android-x86_64"
|
||||
;;
|
||||
arm64-v8a)
|
||||
DESTDIR="$BUILD_DIR/arm64-v8a"
|
||||
SSL_TARGET="android-arm64"
|
||||
;;
|
||||
esac
|
||||
|
||||
rm -rf $DESTDIR
|
||||
build_the_thing
|
||||
#### copy libraries and includes to output-directory #####
|
||||
mkdir -p $OUT_DIR/$build_target/include
|
||||
cp -R $DESTDIR/usr/local/include/* $OUT_DIR/$build_target/include
|
||||
cp -R $DESTDIR/usr/local/ssl/* $OUT_DIR/$build_target/
|
||||
mkdir -p $OUT_DIR/$build_target/lib
|
||||
cp -R $DESTDIR/usr/local/lib/*.so $OUT_DIR/$build_target/lib
|
||||
cp -R $DESTDIR/usr/local/lib/*.a $OUT_DIR/$build_target/lib
|
||||
done
|
||||
|
||||
echo Success
|
3
trunk/3rdparty/srt-1-fit/scripts/build-windows.bat
vendored
Normal file
3
trunk/3rdparty/srt-1-fit/scripts/build-windows.bat
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
@ECHO OFF
|
||||
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\PowerShell.exe -Command "& '%~dpn0.ps1'"
|
||||
pause
|
238
trunk/3rdparty/srt-1-fit/scripts/build-windows.ps1
vendored
Normal file
238
trunk/3rdparty/srt-1-fit/scripts/build-windows.ps1
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
################################################################################
|
||||
# Windows SRT Build Script
|
||||
#============================
|
||||
# Usable on a Windows PC with Powershell and Visual studio,
|
||||
# or called by CI systems like AppVeyor
|
||||
#
|
||||
# By default produces a VS2019 64-bit Release binary using C++11 threads, without
|
||||
# encryption or unit tests enabled, but including test apps.
|
||||
# Before enabling any encryption options, install OpenSSL or set VCKPG flag to build
|
||||
################################################################################
|
||||
|
||||
param (
|
||||
[Parameter()][String]$VS_VERSION = "2019",
|
||||
[Parameter()][String]$CONFIGURATION = "Release",
|
||||
[Parameter()][String]$DEVENV_PLATFORM = "x64",
|
||||
[Parameter()][String]$ENABLE_ENCRYPTION = "OFF",
|
||||
[Parameter()][String]$STATIC_LINK_SSL = "OFF",
|
||||
[Parameter()][String]$CXX11 = "ON",
|
||||
[Parameter()][String]$BUILD_APPS = "ON",
|
||||
[Parameter()][String]$UNIT_TESTS = "OFF",
|
||||
[Parameter()][String]$BUILD_DIR = "_build",
|
||||
[Parameter()][String]$VCPKG_OPENSSL = "OFF",
|
||||
[Parameter()][String]$BONDING = "OFF"
|
||||
)
|
||||
|
||||
# cmake can be optionally installed (useful when running interactively on a developer station).
|
||||
# The URL for automatic download is defined later in the script, but it should be possible to just vary the
|
||||
# specific version set below and the URL should be stable enough to still work - you have been warned.
|
||||
$cmakeVersion = "3.23.2"
|
||||
|
||||
# make all errors trigger a script stop, rather than just carry on
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectRoot = Join-Path $PSScriptRoot "/.." -Resolve
|
||||
|
||||
# if running within AppVeyor, use environment variables to set params instead of passed-in values
|
||||
if ( $Env:APPVEYOR ) {
|
||||
if ( $Env:PLATFORM -eq 'x86' ) { $DEVENV_PLATFORM = 'Win32' } else { $DEVENV_PLATFORM = 'x64' }
|
||||
if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2019' ) { $VS_VERSION='2019' }
|
||||
if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2015' ) { $VS_VERSION='2015' }
|
||||
if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2013' ) { $VS_VERSION='2013' }
|
||||
|
||||
#if not statically linking OpenSSL, set flag to gather the specific openssl package from the build server into package
|
||||
if ( $STATIC_LINK_SSL -eq 'OFF' ) { $Env:GATHER_SSL_INTO_PACKAGE = $true }
|
||||
|
||||
#if unit tests are on, set flag to actually execute ctest step
|
||||
if ( $UNIT_TESTS -eq 'ON' ) { $Env:RUN_UNIT_TESTS = $true }
|
||||
|
||||
$CONFIGURATION = $Env:CONFIGURATION
|
||||
|
||||
#appveyor has many openssl installations - place the latest one in the default location unless VS2013
|
||||
if( $VS_VERSION -ne '2013' ) {
|
||||
Remove-Item -Path "C:\OpenSSL-Win32" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
Remove-Item -Path "C:\OpenSSL-Win64" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
Copy-Item -Path "C:\OpenSSL-v111-Win32" "C:\OpenSSL-Win32" -Recurse | Out-Null
|
||||
Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
# persist VS_VERSION so it can be used in an artifact name later
|
||||
$Env:VS_VERSION = $VS_VERSION
|
||||
|
||||
# select the appropriate cmake generator string given the environment
|
||||
if ( $VS_VERSION -eq '2019' ) { $CMAKE_GENERATOR = 'Visual Studio 16 2019'; $MSBUILDVER = "16.0"; }
|
||||
if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'Win32' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015'; $MSBUILDVER = "14.0"; }
|
||||
if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'x64' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015 Win64'; $MSBUILDVER = "14.0"; }
|
||||
if ( $VS_VERSION -eq '2013' -and $DEVENV_PLATFORM -eq 'Win32' ) { $CMAKE_GENERATOR = 'Visual Studio 12 2013'; $MSBUILDVER = "12.0"; }
|
||||
if ( $VS_VERSION -eq '2013' -and $DEVENV_PLATFORM -eq 'x64' ) { $CMAKE_GENERATOR = 'Visual Studio 12 2013 Win64'; $MSBUILDVER = "12.0"; }
|
||||
|
||||
# clear any previous build and create & enter the build directory
|
||||
$buildDir = Join-Path "$projectRoot" "$BUILD_DIR"
|
||||
Write-Output "Creating (or cleaning if already existing) the folder $buildDir for project files and outputs"
|
||||
Remove-Item -Path $buildDir -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item -ItemType Directory -Path $buildDir -ErrorAction SilentlyContinue | Out-Null
|
||||
Push-Location $buildDir
|
||||
|
||||
# check cmake is installed
|
||||
if ( $null -eq (Get-Command "cmake.exe" -ErrorAction SilentlyContinue) ) {
|
||||
$installCmake = Read-Host "Unable to find cmake in your PATH - would you like to download and install automatically? [yes/no]"
|
||||
|
||||
if ( $installCmake -eq "y" -or $installCmake -eq "yes" ) {
|
||||
# download cmake and run MSI for user
|
||||
$client = New-Object System.Net.WebClient
|
||||
$tempDownloadFile = New-TemporaryFile
|
||||
|
||||
$cmakeUrl = "https://github.com/Kitware/CMake/releases/download/v$cmakeVersion/cmake-$cmakeVersion-win64-x64.msi"
|
||||
$cmakeMsiFile = "$tempDownloadFile.cmake-$cmakeVersion-win64-x64.msi"
|
||||
Write-Output "Downloading cmake from $cmakeUrl (temporary file location $cmakeMsiFile)"
|
||||
Write-Output "Note: select the option to add cmake to path for this script to operate"
|
||||
$client.DownloadFile("$cmakeUrl", "$cmakeMsiFile")
|
||||
Start-Process $cmakeMsiFile -Wait
|
||||
Remove-Item $cmakeMsiFile
|
||||
Write-Output "Cmake should have installed, this script will now exit because of path updates - please now re-run this script"
|
||||
throw
|
||||
}
|
||||
else{
|
||||
Write-Output "Quitting because cmake is required"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
# get pthreads from nuget if CXX11 is not enabled
|
||||
if ( $CXX11 -eq "OFF" ) {
|
||||
# get pthreads (this is legacy, and is only available in nuget for VS2015 and VS2013)
|
||||
if ( $VS_VERSION -gt 2015 ) {
|
||||
Write-Output "Pthreads is not recommended for use beyond VS2015 and is not supported by this build script - aborting build"
|
||||
throw
|
||||
}
|
||||
if ( $DEVENV_PLATFORM -eq 'Win32' ) {
|
||||
nuget install cinegy.pthreads-win32-$VS_VERSION -version 2.9.1.24 -OutputDirectory ../_packages
|
||||
}
|
||||
else {
|
||||
nuget install cinegy.pthreads-win64-$VS_VERSION -version 2.9.1.24 -OutputDirectory ../_packages
|
||||
}
|
||||
}
|
||||
|
||||
# check to see if static SSL linking was requested, and enable encryption if not already ON
|
||||
if ( $STATIC_LINK_SSL -eq "ON" ) {
|
||||
if ( $ENABLE_ENCRYPTION -eq "OFF" ) {
|
||||
# requesting a static link implicitly requires encryption support
|
||||
Write-Output "Static linking to OpenSSL requested, will force encryption feature ON"
|
||||
$ENABLE_ENCRYPTION = "ON"
|
||||
}
|
||||
}
|
||||
|
||||
# check to see if VCPKG is marked to provide OpenSSL, and enable encryption if not already ON
|
||||
if ( $VCPKG_OPENSSL -eq "ON" ) {
|
||||
if ( $ENABLE_ENCRYPTION -eq "OFF" ) {
|
||||
# requesting VCPKG to provide OpenSSL requires encryption support
|
||||
Write-Output "VCPKG compilation of OpenSSL requested, will force encryption feature ON"
|
||||
$ENABLE_ENCRYPTION = "ON"
|
||||
}
|
||||
}
|
||||
|
||||
# build the cmake command flags from arguments
|
||||
$cmakeFlags = "-DCMAKE_BUILD_TYPE=$CONFIGURATION " +
|
||||
"-DENABLE_STDCXX_SYNC=$CXX11 " +
|
||||
"-DENABLE_APPS=$BUILD_APPS " +
|
||||
"-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " +
|
||||
"-DENABLE_BONDING=$BONDING " +
|
||||
"-DENABLE_UNITTESTS=$UNIT_TESTS"
|
||||
|
||||
# if VCPKG is flagged to provide OpenSSL, checkout VCPKG and install package
|
||||
if ( $VCPKG_OPENSSL -eq 'ON' ) {
|
||||
Push-Location $projectRoot
|
||||
Write-Output "Cloning VCPKG into: $(Get-Location)"
|
||||
if (Test-Path -Path ".\vcpkg") {
|
||||
Set-Location .\vcpkg
|
||||
git pull
|
||||
} else {
|
||||
git clone https://github.com/microsoft/vcpkg
|
||||
Set-Location .\vcpkg
|
||||
}
|
||||
|
||||
.\bootstrap-vcpkg.bat
|
||||
|
||||
if($DEVENV_PLATFORM -EQ "x64"){
|
||||
if($STATIC_LINK_SSL -EQ "ON"){
|
||||
.\vcpkg install openssl:x64-windows-static
|
||||
$cmakeFlags += " -DVCPKG_TARGET_TRIPLET=x64-windows-static"
|
||||
}
|
||||
else{
|
||||
.\vcpkg install openssl:x64-windows
|
||||
}
|
||||
}
|
||||
else{
|
||||
if($STATIC_LINK_SSL -EQ "ON"){
|
||||
.\vcpkg install openssl:x86-windows-static
|
||||
$cmakeFlags += " -DVCPKG_TARGET_TRIPLET=x86-windows-static"
|
||||
}
|
||||
else{
|
||||
.\vcpkg install openssl:x86-windows
|
||||
}
|
||||
}
|
||||
|
||||
.\vcpkg integrate install
|
||||
Pop-Location
|
||||
$cmakeFlags += " -DCMAKE_TOOLCHAIN_FILE=$projectRoot\vcpkg\scripts\buildsystems\vcpkg.cmake"
|
||||
}
|
||||
else {
|
||||
$cmakeFlags += " -DOPENSSL_USE_STATIC_LIBS=$STATIC_LINK_SSL "
|
||||
}
|
||||
|
||||
# cmake uses a flag for architecture from vs2019, so add that as a suffix
|
||||
if ( $VS_VERSION -eq '2019' ) {
|
||||
$cmakeFlags += " -A `"$DEVENV_PLATFORM`""
|
||||
}
|
||||
|
||||
# fire cmake to build project files
|
||||
$execVar = "cmake ../ -G`"$CMAKE_GENERATOR`" $cmakeFlags"
|
||||
Write-Output $execVar
|
||||
|
||||
# Reset reaction to Continue for cmake as it sometimes tends to print
|
||||
# things on stderr, which is understood by PowerShell as error. The
|
||||
# exit code from cmake will be checked anyway.
|
||||
$ErrorActionPreference = "Continue"
|
||||
Invoke-Expression "& $execVar"
|
||||
|
||||
# check build ran OK, exit if cmake failed
|
||||
if( $LASTEXITCODE -ne 0 ) {
|
||||
Write-Output "Non-zero exit code from cmake: $LASTEXITCODE"
|
||||
throw
|
||||
}
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# run the set-version-metadata script to inject build numbers into appveyors console and the resulting DLL
|
||||
. $PSScriptRoot/set-version-metadata.ps1
|
||||
|
||||
# look for msbuild
|
||||
$msBuildPath = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue
|
||||
if ( $null -eq $msBuildPath ) {
|
||||
# no mbsuild in the path, so try to locate with 'vswhere'
|
||||
$vsWherePath = Get-Command "vswhere.exe" -ErrorAction SilentlyContinue
|
||||
if ( $null -eq $vsWherePath ) {
|
||||
# no vswhere in the path, so check the Microsoft published location (true since VS2017 Update 2)
|
||||
$vsWherePath = Get-Command "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -ErrorAction SilentlyContinue
|
||||
if ( $null -eq $vsWherePath ) {
|
||||
Write-Output "Cannot find vswhere (used to locate msbuild). Please install VS2017 update 2 (or later) or add vswhere to your path and try again"
|
||||
throw
|
||||
}
|
||||
}
|
||||
$msBuildPath = & $vsWherePath -products * -version $MSBUILDVER -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
|
||||
if ( $null -eq $msBuildPath ) {
|
||||
Write-Output "vswhere.exe cannot find msbuild for the specified Visual Studio version - please check the installation"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
& $msBuildPath SRT.sln -m /p:Configuration=$CONFIGURATION /p:Platform=$DEVENV_PLATFORM
|
||||
|
||||
# return to the directory previously occupied before running the script
|
||||
Pop-Location
|
||||
|
||||
# if msbuild returned non-zero, throw to cause failure in CI
|
||||
if( $LASTEXITCODE -ne 0 ) {
|
||||
throw
|
||||
}
|
7
trunk/3rdparty/srt-1-fit/scripts/collect-gcov.sh
vendored
Normal file
7
trunk/3rdparty/srt-1-fit/scripts/collect-gcov.sh
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
shopt -s globstar
|
||||
gcov_data_dir="."
|
||||
for x in ./**/*.o; do
|
||||
echo "x: $x"
|
||||
gcov "$gcov_data_dir/$x"
|
||||
done
|
|
@ -15,7 +15,9 @@ md %APPVEYOR_BUILD_FOLDER%\package\include
|
|||
md %APPVEYOR_BUILD_FOLDER%\package\include\win
|
||||
md %APPVEYOR_BUILD_FOLDER%\package\bin
|
||||
md %APPVEYOR_BUILD_FOLDER%\package\lib
|
||||
md %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM%
|
||||
IF "%GATHER_SSL_INTO_PACKAGE%"=="True" (
|
||||
md %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM%
|
||||
)
|
||||
|
||||
rem Gather SRT includes, binaries and libs
|
||||
copy %APPVEYOR_BUILD_FOLDER%\version.h %APPVEYOR_BUILD_FOLDER%\package\include\
|
||||
|
@ -23,13 +25,13 @@ copy %APPVEYOR_BUILD_FOLDER%\srtcore\*.h %APPVEYOR_BUILD_FOLDER%\package\include
|
|||
copy %APPVEYOR_BUILD_FOLDER%\haicrypt\*.h %APPVEYOR_BUILD_FOLDER%\package\include\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\common\*.h %APPVEYOR_BUILD_FOLDER%\package\include\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\common\win\*.h %APPVEYOR_BUILD_FOLDER%\package\include\win\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\%CONFIGURATION%\*.exe %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\%CONFIGURATION%\*.dll %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\%CONFIGURATION%\*.lib %APPVEYOR_BUILD_FOLDER%\package\lib\
|
||||
IF "%CONFIGURATION%"=="Debug" (
|
||||
copy %APPVEYOR_BUILD_FOLDER%\%CONFIGURATION%\*.pdb %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
)
|
||||
copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.exe %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.dll %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.lib %APPVEYOR_BUILD_FOLDER%\package\lib\
|
||||
copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.pdb %APPVEYOR_BUILD_FOLDER%\package\bin\
|
||||
|
||||
rem gather 3rd party openssl elements
|
||||
(robocopy c:\openssl-win%FOLDER_PLATFORM%\ %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% /s /e /np) ^& IF %ERRORLEVEL% GTR 1 exit %ERRORLEVEL%
|
||||
rem Gather 3rd party openssl elements
|
||||
IF "%GATHER_SSL_INTO_PACKAGE%"=="True" (
|
||||
(robocopy c:\openssl-win%FOLDER_PLATFORM%\ %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% /s /e /np) ^& IF %ERRORLEVEL% GTR 1 exit %ERRORLEVEL%
|
||||
)
|
||||
exit 0
|
||||
|
|
251
trunk/3rdparty/srt-1-fit/scripts/generate-error-types.tcl
vendored
Executable file
251
trunk/3rdparty/srt-1-fit/scripts/generate-error-types.tcl
vendored
Executable file
|
@ -0,0 +1,251 @@
|
|||
#!/usr/bin/tclsh
|
||||
#*
|
||||
#* SRT - Secure, Reliable, Transport
|
||||
#* Copyright (c) 2020 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.
|
||||
#*****************************************************************************
|
||||
|
||||
set code_major {
|
||||
UNKNOWN -1
|
||||
SUCCESS 0
|
||||
SETUP 1
|
||||
CONNECTION 2
|
||||
SYSTEMRES 3
|
||||
FILESYSTEM 4
|
||||
NOTSUP 5
|
||||
AGAIN 6
|
||||
PEERERROR 7
|
||||
}
|
||||
|
||||
set code_minor {
|
||||
NONE 0
|
||||
TIMEOUT 1
|
||||
REJECTED 2
|
||||
NORES 3
|
||||
SECURITY 4
|
||||
CLOSED 5
|
||||
|
||||
|
||||
CONNLOST 1
|
||||
NOCONN 2
|
||||
|
||||
THREAD 1
|
||||
MEMORY 2
|
||||
OBJECT 3
|
||||
|
||||
SEEKGFAIL 1
|
||||
READFAIL 2
|
||||
SEEKPFAIL 3
|
||||
WRITEFAIL 4
|
||||
|
||||
ISBOUND 1
|
||||
ISCONNECTED 2
|
||||
INVAL 3
|
||||
SIDINVAL 4
|
||||
ISUNBOUND 5
|
||||
NOLISTEN 6
|
||||
ISRENDEZVOUS 7
|
||||
ISRENDUNBOUND 8
|
||||
INVALMSGAPI 9
|
||||
INVALBUFFERAPI 10
|
||||
BUSY 11
|
||||
XSIZE 12
|
||||
EIDINVAL 13
|
||||
EEMPTY 14
|
||||
BUSYPORT 15
|
||||
|
||||
WRAVAIL 1
|
||||
RDAVAIL 2
|
||||
XMTIMEOUT 3
|
||||
CONGESTION 4
|
||||
}
|
||||
|
||||
|
||||
set errortypes {
|
||||
|
||||
SUCCESS "Success" {
|
||||
NONE ""
|
||||
}
|
||||
|
||||
SETUP "Connection setup failure" {
|
||||
NONE ""
|
||||
TIMEOUT "connection timed out"
|
||||
REJECTED "connection rejected"
|
||||
NORES "unable to create/configure SRT socket"
|
||||
SECURITY "aborted for security reasons"
|
||||
CLOSED "socket closed during operation"
|
||||
}
|
||||
|
||||
CONNECTION "" {
|
||||
NONE ""
|
||||
CONNLOST "Connection was broken"
|
||||
NOCONN "Connection does not exist"
|
||||
}
|
||||
|
||||
SYSTEMRES "System resource failure" {
|
||||
NONE ""
|
||||
THREAD "unable to create new threads"
|
||||
MEMORY "unable to allocate buffers"
|
||||
OBJECT "unable to allocate a system object"
|
||||
}
|
||||
|
||||
FILESYSTEM "File system failure" {
|
||||
NONE ""
|
||||
SEEKGFAIL "cannot seek read position"
|
||||
READFAIL "failure in read"
|
||||
SEEKPFAIL "cannot seek write position"
|
||||
WRITEFAIL "failure in write"
|
||||
}
|
||||
|
||||
NOTSUP "Operation not supported" {
|
||||
NONE ""
|
||||
ISBOUND "Cannot do this operation on a BOUND socket"
|
||||
ISCONNECTED "Cannot do this operation on a CONNECTED socket"
|
||||
INVAL "Bad parameters"
|
||||
SIDINVAL "Invalid socket ID"
|
||||
ISUNBOUND "Cannot do this operation on an UNBOUND socket"
|
||||
NOLISTEN "Socket is not in listening state"
|
||||
ISRENDEZVOUS "Listen/accept is not supported in rendezvous connection setup"
|
||||
ISRENDUNBOUND "Cannot call connect on UNBOUND socket in rendezvous connection setup"
|
||||
INVALMSGAPI "Incorrect use of Message API (sendmsg/recvmsg)."
|
||||
INVALBUFFERAPI "Incorrect use of Buffer API (send/recv) or File API (sendfile/recvfile)."
|
||||
BUSY "Another socket is already listening on the same port"
|
||||
XSIZE "Message is too large to send (it must be less than the SRT send buffer size)"
|
||||
EIDINVAL "Invalid epoll ID"
|
||||
EEMPTY "All sockets removed from epoll, waiting would deadlock"
|
||||
BUSYPORT "Another socket is bound to that port and is not reusable for requested settings"
|
||||
}
|
||||
|
||||
AGAIN "Non-blocking call failure" {
|
||||
NONE ""
|
||||
WRAVAIL "no buffer available for sending"
|
||||
RDAVAIL "no data available for reading"
|
||||
XMTIMEOUT "transmission timed out"
|
||||
CONGESTION "early congestion notification"
|
||||
}
|
||||
|
||||
PEERERROR "The peer side has signaled an error" {
|
||||
NONE ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set main_array_item {
|
||||
const char** strerror_array_major [] = {
|
||||
$minor_array_list
|
||||
};
|
||||
}
|
||||
|
||||
set major_size_item {
|
||||
const size_t strerror_array_sizes [] = {
|
||||
$minor_array_sizes
|
||||
};
|
||||
}
|
||||
|
||||
set minor_array_item {
|
||||
const char* strerror_msgs_$majorlc [] = {
|
||||
$minor_message_items
|
||||
};
|
||||
}
|
||||
|
||||
set strerror_function {
|
||||
const char* strerror_get_message(size_t major, size_t minor)
|
||||
{
|
||||
static const char* const undefined = "UNDEFINED ERROR";
|
||||
|
||||
// Extract the major array
|
||||
if (major >= sizeof(strerror_array_major)/sizeof(const char**))
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const char** array = strerror_array_major[major];
|
||||
size_t size = strerror_array_sizes[major];
|
||||
|
||||
if (minor >= size)
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return array[minor];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set globalheader {
|
||||
/*
|
||||
WARNING: Generated from ../scripts/generate-error-types.tcl
|
||||
|
||||
DO NOT MODIFY.
|
||||
|
||||
Copyright applies as per the generator script.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
}
|
||||
|
||||
proc Generate:imp {} {
|
||||
|
||||
puts $::globalheader
|
||||
|
||||
puts "namespace srt\n\{"
|
||||
|
||||
# Generate major array
|
||||
set majitem 0
|
||||
set minor_array_sizes ""
|
||||
foreach {mt mm cont} $::errortypes {
|
||||
|
||||
puts "// MJ_$mt '$mm'"
|
||||
|
||||
# Generate minor array
|
||||
set majorlc [string tolower $mt]
|
||||
set minor_message_items ""
|
||||
set minitem 0
|
||||
foreach {mnt mnm} $cont {
|
||||
if {$mm == ""} {
|
||||
set msg $mnm
|
||||
} elseif {$mnm == ""} {
|
||||
set msg $mm
|
||||
} else {
|
||||
set msg "$mm: $mnm"
|
||||
}
|
||||
append minor_message_items " \"$msg\", // MN_$mnt = $minitem\n"
|
||||
incr minitem
|
||||
}
|
||||
append minor_message_items " \"\""
|
||||
puts [subst -nobackslashes -nocommands $::minor_array_item]
|
||||
|
||||
append minor_array_list " strerror_msgs_$majorlc, // MJ_$mt = $majitem\n"
|
||||
#append minor_array_sizes " [expr {$minitem}],\n"
|
||||
append minor_array_sizes " SRT_ARRAY_SIZE(strerror_msgs_$majorlc) - 1,\n"
|
||||
incr majitem
|
||||
}
|
||||
append minor_array_list " NULL"
|
||||
append minor_array_sizes " 0"
|
||||
|
||||
puts [subst -nobackslashes -nocommands $::main_array_item]
|
||||
puts {#define SRT_ARRAY_SIZE(ARR) sizeof(ARR) / sizeof(ARR[0])}
|
||||
puts [subst -nobackslashes -nocommands $::major_size_item]
|
||||
|
||||
puts $::strerror_function
|
||||
|
||||
puts "\} // namespace srt"
|
||||
}
|
||||
|
||||
|
||||
set defmode imp
|
||||
if {[lindex $argv 0] != ""} {
|
||||
set defmode [lindex $argv 0]
|
||||
}
|
||||
|
||||
Generate:$defmode
|
454
trunk/3rdparty/srt-1-fit/scripts/generate-logging-defs.tcl
vendored
Executable file
454
trunk/3rdparty/srt-1-fit/scripts/generate-logging-defs.tcl
vendored
Executable file
|
@ -0,0 +1,454 @@
|
|||
#!/usr/bin/tclsh
|
||||
#*
|
||||
#* SRT - Secure, Reliable, Transport
|
||||
#* Copyright (c) 2020 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.
|
||||
#*****************************************************************************
|
||||
|
||||
# What fields are there in every entry
|
||||
set model {
|
||||
longname
|
||||
shortname
|
||||
id
|
||||
description
|
||||
}
|
||||
|
||||
# Logger definitions.
|
||||
# Comments here allowed, just only for the whole line.
|
||||
|
||||
# Use values greater than 0. Value 0 is reserved for LOGFA_GENERAL,
|
||||
# which is considered always enabled.
|
||||
set loggers {
|
||||
GENERAL gg 0 "General uncategorized log, for serious issues only"
|
||||
SOCKMGMT sm 1 "Socket create/open/close/configure activities"
|
||||
CONN cn 2 "Connection establishment and handshake"
|
||||
XTIMER xt 3 "The checkTimer and around activities"
|
||||
TSBPD ts 4 "The TsBPD thread"
|
||||
RSRC rs 5 "System resource allocation and management"
|
||||
CONGEST cc 7 "Congestion control module"
|
||||
PFILTER pf 8 "Packet filter module"
|
||||
API_CTRL ac 11 "API part for socket and library managmenet"
|
||||
QUE_CTRL qc 13 "Queue control activities"
|
||||
EPOLL_UPD ei 16 "EPoll, internal update activities"
|
||||
|
||||
API_RECV ar 21 "API part for receiving"
|
||||
BUF_RECV br 22 "Buffer, receiving side"
|
||||
QUE_RECV qr 23 "Queue, receiving side"
|
||||
CHN_RECV kr 24 "CChannel, receiving side"
|
||||
GRP_RECV gr 25 "Group, receiving side"
|
||||
|
||||
API_SEND as 31 "API part for sending"
|
||||
BUF_SEND bs 32 "Buffer, sending side"
|
||||
QUE_SEND qs 33 "Queue, sending side"
|
||||
CHN_SEND ks 34 "CChannel, sending side"
|
||||
GRP_SEND gs 35 "Group, sending side"
|
||||
|
||||
INTERNAL in 41 "Internal activities not connected directly to a socket"
|
||||
QUE_MGMT qm 43 "Queue, management part"
|
||||
CHN_MGMT km 44 "CChannel, management part"
|
||||
GRP_MGMT gm 45 "Group, management part"
|
||||
EPOLL_API ea 46 "EPoll, API part"
|
||||
}
|
||||
|
||||
set hidden_loggers {
|
||||
# Haicrypt logging - usually off.
|
||||
HAICRYPT hc 6 "Haicrypt module area"
|
||||
|
||||
# defined in apps, this is only a stub to lock the value
|
||||
APPLOG ap 10 "Applications"
|
||||
}
|
||||
|
||||
set globalheader {
|
||||
/*
|
||||
WARNING: Generated from ../scripts/generate-logging-defs.tcl
|
||||
|
||||
DO NOT MODIFY.
|
||||
|
||||
Copyright applies as per the generator script.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
# This defines, what kind of definition will be generated
|
||||
# for a given file out of the log FA entry list.
|
||||
|
||||
# Fields:
|
||||
# - prefix/postfix model
|
||||
# - logger_format
|
||||
# - hidden_logger_format
|
||||
|
||||
# COMMENTS NOT ALLOWED HERE! Only as C++ comments inside C++ model code.
|
||||
set special {
|
||||
srtcore/logger_default.cpp {
|
||||
if {"$longname" == "HAICRYPT"} {
|
||||
puts $od "
|
||||
#if ENABLE_HAICRYPT_LOGGING
|
||||
allfa.set(SRT_LOGFA_HAICRYPT, true);
|
||||
#endif"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc GenerateModelForSrtH {} {
|
||||
|
||||
# `path` will be set to the git top path
|
||||
global path
|
||||
|
||||
set fd [open [file join $path srtcore/srt.h] r]
|
||||
|
||||
set contents ""
|
||||
|
||||
set state read
|
||||
set pass looking
|
||||
|
||||
while { [gets $fd line] != -1 } {
|
||||
if { $state == "read" } {
|
||||
|
||||
if { $pass != "passed" } {
|
||||
|
||||
set re [regexp {SRT_LOGFA BEGIN GENERATED SECTION} $line]
|
||||
if {$re} {
|
||||
set state skip
|
||||
set pass found
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
append contents "$line\n"
|
||||
continue
|
||||
}
|
||||
|
||||
if {$state == "skip"} {
|
||||
if { [string trim $line] == "" } {
|
||||
# Empty line, continue skipping
|
||||
continue
|
||||
}
|
||||
|
||||
set re [regexp {SRT_LOGFA END GENERATED SECTION} $line]
|
||||
if {!$re} {
|
||||
# Still SRT_LOGFA definitions
|
||||
continue
|
||||
}
|
||||
|
||||
# End of generated section. Switch back to pass-thru.
|
||||
|
||||
# First fill the gap
|
||||
append contents "\n\$entries\n\n"
|
||||
|
||||
append contents "$line\n"
|
||||
set state read
|
||||
set pass passed
|
||||
}
|
||||
}
|
||||
|
||||
close $fd
|
||||
|
||||
# Sanity check
|
||||
if {$pass != "passed"} {
|
||||
error "Invalid contents of `srt.h` file, can't find '#define SRT_LOGFA_' phrase"
|
||||
}
|
||||
|
||||
return $contents
|
||||
}
|
||||
|
||||
# COMMENTS NOT ALLOWED HERE! Only as C++ comments inside C++ model code.
|
||||
# (NOTE: Tcl syntax highlighter will likely falsely highlight # as comment here)
|
||||
#
|
||||
# Model: TARGET-NAME { format-model logger-pattern hidden-logger-pattern }
|
||||
#
|
||||
# Special syntax:
|
||||
#
|
||||
# %<command> : a high-level command execution. This declares a command that
|
||||
# must be executed to GENERATE the model. Then, [subst] is executed
|
||||
# on the results.
|
||||
#
|
||||
# = : when placed as the hidden-logger-pattern, it's equal to logger-pattern.
|
||||
#
|
||||
set generation {
|
||||
srtcore/srt.h {
|
||||
|
||||
{%GenerateModelForSrtH}
|
||||
|
||||
{#define [format "%-20s %-3d" SRT_LOGFA_${longname} $id] // ${shortname}log: $description}
|
||||
|
||||
=
|
||||
}
|
||||
|
||||
srtcore/logger_default.cpp {
|
||||
|
||||
{
|
||||
$globalheader
|
||||
#include "srt.h"
|
||||
#include "logging.h"
|
||||
#include "logger_defs.h"
|
||||
|
||||
namespace srt_logging
|
||||
{
|
||||
AllFaOn::AllFaOn()
|
||||
{
|
||||
$entries
|
||||
}
|
||||
} // namespace srt_logging
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
allfa.set(SRT_LOGFA_${longname}, true);
|
||||
}
|
||||
}
|
||||
|
||||
srtcore/logger_defs.cpp {
|
||||
|
||||
{
|
||||
$globalheader
|
||||
#include "srt.h"
|
||||
#include "logging.h"
|
||||
#include "logger_defs.h"
|
||||
|
||||
namespace srt_logging { AllFaOn logger_fa_all; }
|
||||
// We need it outside the namespace to preserve the global name.
|
||||
// It's a part of "hidden API" (used by applications)
|
||||
SRT_API srt_logging::LogConfig srt_logger_config(srt_logging::logger_fa_all.allfa);
|
||||
|
||||
namespace srt_logging
|
||||
{
|
||||
$entries
|
||||
} // namespace srt_logging
|
||||
}
|
||||
|
||||
{
|
||||
Logger ${shortname}log(SRT_LOGFA_${longname}, srt_logger_config, "SRT.${shortname}");
|
||||
}
|
||||
}
|
||||
|
||||
srtcore/logger_defs.h {
|
||||
{
|
||||
$globalheader
|
||||
#ifndef INC_SRT_LOGGER_DEFS_H
|
||||
#define INC_SRT_LOGGER_DEFS_H
|
||||
|
||||
#include "srt.h"
|
||||
#include "logging.h"
|
||||
|
||||
namespace srt_logging
|
||||
{
|
||||
struct AllFaOn
|
||||
{
|
||||
LogConfig::fa_bitset_t allfa;
|
||||
AllFaOn();
|
||||
};
|
||||
|
||||
$entries
|
||||
|
||||
} // namespace srt_logging
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
extern Logger ${shortname}log;
|
||||
}
|
||||
}
|
||||
|
||||
apps/logsupport_appdefs.cpp {
|
||||
{
|
||||
$globalheader
|
||||
#include "logsupport.hpp"
|
||||
|
||||
LogFANames::LogFANames()
|
||||
{
|
||||
$entries
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Install("$longname", SRT_LOGFA_${longname});
|
||||
}
|
||||
|
||||
{
|
||||
Install("$longname", SRT_LOGFA_${longname});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# EXECUTION
|
||||
|
||||
set here [file dirname [file normalize $argv0]]
|
||||
|
||||
if {[lindex [file split $here] end] != "scripts"} {
|
||||
puts stderr "The script is in weird location."
|
||||
exit 1
|
||||
}
|
||||
|
||||
set path [file join {*}[lrange [file split $here] 0 end-1]]
|
||||
|
||||
# Utility. Allows to put line-oriented comments and have empty lines
|
||||
proc no_comments {input} {
|
||||
set output ""
|
||||
foreach line [split $input \n] {
|
||||
set nn [string trim $line]
|
||||
if { $nn == "" || [string index $nn 0] == "#" } {
|
||||
continue
|
||||
}
|
||||
append output $line\n
|
||||
}
|
||||
|
||||
return $output
|
||||
}
|
||||
|
||||
proc generate_file {od target} {
|
||||
|
||||
global globalheader
|
||||
lassign [dict get $::generation $target] format_model pattern hpattern
|
||||
|
||||
set ptabprefix ""
|
||||
|
||||
if {[string index $format_model 0] == "%"} {
|
||||
set command [string range $format_model 1 end]
|
||||
set format_model [eval $command]
|
||||
}
|
||||
|
||||
if {$format_model != ""} {
|
||||
set beginindex 0
|
||||
while { [string index $format_model $beginindex] == "\n" } {
|
||||
incr beginindex
|
||||
}
|
||||
|
||||
set endindex $beginindex
|
||||
while { [string is space [string index $format_model $endindex]] } {
|
||||
incr endindex
|
||||
}
|
||||
|
||||
set tabprefix [string range $pattern $beginindex $endindex-1]
|
||||
|
||||
set newformat ""
|
||||
foreach line [split $format_model \n] {
|
||||
if {[string trim $line] == ""} {
|
||||
append newformat "\n"
|
||||
continue
|
||||
}
|
||||
|
||||
if {[string first $tabprefix $line] == 0} {
|
||||
set line [string range $line [string length $tabprefix] end]
|
||||
}
|
||||
append newformat $line\n
|
||||
|
||||
set ie [string first {$} $line]
|
||||
if {$ie != -1} {
|
||||
if {[string range $line $ie end] == {$entries}} {
|
||||
set ptabprefix "[string range $line 0 $ie-1]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set format_model $newformat
|
||||
unset newformat
|
||||
}
|
||||
|
||||
set entries ""
|
||||
|
||||
if {[string trim $pattern] != "" } {
|
||||
|
||||
set prevval 0
|
||||
set pattern [string trim $pattern]
|
||||
|
||||
# The first "$::model" will expand into variable names
|
||||
# as defined there.
|
||||
foreach [list {*}$::model] [no_comments $::loggers] {
|
||||
if {$prevval + 1 != $id} {
|
||||
append entries "\n"
|
||||
}
|
||||
|
||||
append entries "${ptabprefix}[subst -nobackslashes $pattern]\n"
|
||||
set prevval $id
|
||||
}
|
||||
}
|
||||
|
||||
if {$hpattern != ""} {
|
||||
if {$hpattern == "="} {
|
||||
set hpattern $pattern
|
||||
} else {
|
||||
set hpattern [string trim $hpattern]
|
||||
}
|
||||
|
||||
# Extra line to separate from the normal entries
|
||||
append entries "\n"
|
||||
foreach [list {*}$::model] [no_comments $::hidden_loggers] {
|
||||
append entries "${ptabprefix}[subst -nobackslashes $hpattern]\n"
|
||||
}
|
||||
}
|
||||
|
||||
if { [dict exists $::special $target] } {
|
||||
set code [subst [dict get $::special $target]]
|
||||
|
||||
# The code should contain "append entries" !
|
||||
eval $code
|
||||
}
|
||||
|
||||
set entries [string trim $entries]
|
||||
|
||||
if {$format_model == ""} {
|
||||
set format_model $entries
|
||||
}
|
||||
|
||||
# For any case, cut external spaces
|
||||
puts $od [string trim [subst -nocommands -nobackslashes $format_model]]
|
||||
}
|
||||
|
||||
proc debug_vars {list} {
|
||||
set output ""
|
||||
foreach name $list {
|
||||
upvar $name _${name}
|
||||
lappend output "${name}=[set _${name}]"
|
||||
}
|
||||
|
||||
return $output
|
||||
}
|
||||
|
||||
# MAIN
|
||||
|
||||
set entryfiles $argv
|
||||
|
||||
if {$entryfiles == ""} {
|
||||
set entryfiles [dict keys $generation]
|
||||
} else {
|
||||
foreach ef $entryfiles {
|
||||
if { $ef ni [dict keys $generation] } {
|
||||
error "Unknown generation target: $entryfiles"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach f $entryfiles {
|
||||
|
||||
# Set simple relative path, if the file isn't defined as path.
|
||||
if { [llength [file split $f]] == 1 } {
|
||||
set filepath $f
|
||||
} else {
|
||||
set filepath [file join $path $f]
|
||||
}
|
||||
|
||||
puts stderr "Generating '$filepath'"
|
||||
set od [open $filepath.tmp w]
|
||||
generate_file $od $f
|
||||
close $od
|
||||
if { [file exists $filepath] } {
|
||||
puts "WARNING: will overwrite exiting '$f'. Hit ENTER to confirm, or Control-C to stop"
|
||||
gets stdin
|
||||
}
|
||||
|
||||
file rename -force $filepath.tmp $filepath
|
||||
}
|
||||
|
||||
puts stderr Done.
|
||||
|
|
@ -11,7 +11,7 @@ ExternalProject_Add(
|
|||
BINARY_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-build"
|
||||
GIT_REPOSITORY
|
||||
https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.8.1
|
||||
GIT_TAG release-1.10.0
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
229
trunk/3rdparty/srt-1-fit/scripts/haiUtil.cmake
vendored
229
trunk/3rdparty/srt-1-fit/scripts/haiUtil.cmake
vendored
|
@ -12,11 +12,11 @@ include(CheckCXXSourceCompiles)
|
|||
# Useful for combinging paths
|
||||
|
||||
function(adddirname prefix lst out_lst)
|
||||
set(output)
|
||||
foreach(item ${lst})
|
||||
list(APPEND output "${prefix}/${item}")
|
||||
endforeach()
|
||||
set(${out_lst} ${${out_lst}} ${output} PARENT_SCOPE)
|
||||
set(output)
|
||||
foreach(item ${lst})
|
||||
list(APPEND output "${prefix}/${item}")
|
||||
endforeach()
|
||||
set(${out_lst} ${${out_lst}} ${output} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Splits a version formed as "major.minor.patch" recorded in variable 'prefix'
|
||||
|
@ -32,11 +32,11 @@ ENDMACRO(set_version_variables)
|
|||
# Sets given variable to 1, if the condition that follows it is satisfied.
|
||||
# Otherwise set it to 0.
|
||||
MACRO(set_if varname)
|
||||
IF(${ARGN})
|
||||
SET(${varname} 1)
|
||||
ELSE(${ARGN})
|
||||
SET(${varname} 0)
|
||||
ENDIF(${ARGN})
|
||||
IF(${ARGN})
|
||||
SET(${varname} 1)
|
||||
ELSE(${ARGN})
|
||||
SET(${varname} 0)
|
||||
ENDIF(${ARGN})
|
||||
ENDMACRO(set_if)
|
||||
|
||||
FUNCTION(join_arguments outvar)
|
||||
|
@ -49,83 +49,8 @@ FUNCTION(join_arguments outvar)
|
|||
set (${outvar} ${output} PARENT_SCOPE)
|
||||
ENDFUNCTION()
|
||||
|
||||
# LEGACY. PLEASE DON'T USE ANYMORE.
|
||||
MACRO(MafRead maffile)
|
||||
message(WARNING "MafRead is deprecated. Please use MafReadDir instead")
|
||||
# ARGN contains the extra "section-variable" pairs
|
||||
# If empty, return nothing
|
||||
set (MAFREAD_TAGS
|
||||
SOURCES # source files
|
||||
PUBLIC_HEADERS # installable headers for include
|
||||
PROTECTED_HEADERS # installable headers used by other headers
|
||||
PRIVATE_HEADERS # non-installable headers
|
||||
)
|
||||
cmake_parse_arguments(MAFREAD_VAR "" "${MAFREAD_TAGS}" "" ${ARGN})
|
||||
# Arguments for these tags are variables to be filled
|
||||
# with the contents of particular section.
|
||||
# While reading the file, extract the section.
|
||||
# Section is recognized by either first uppercase character or space.
|
||||
|
||||
# @c http://cmake.org/pipermail/cmake/2007-May/014222.html
|
||||
FILE(READ ${maffile} MAFREAD_CONTENTS)
|
||||
STRING(REGEX REPLACE ";" "\\\\;" MAFREAD_CONTENTS "${MAFREAD_CONTENTS}")
|
||||
STRING(REGEX REPLACE "\n" ";" MAFREAD_CONTENTS "${MAFREAD_CONTENTS}")
|
||||
|
||||
#message("DEBUG: MAF FILE CONTENTS: ${MAFREAD_CONTENTS}")
|
||||
#message("DEBUG: PASSED VARIABLES:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# message("DEBUG: ${DEBUG_VAR}=${MAFREAD_VAR_${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
|
||||
# The unnamed section becomes SOURCES
|
||||
set (MAFREAD_VARIABLE ${MAFREAD_VAR_SOURCES})
|
||||
set (MAFREAD_UNASSIGNED "")
|
||||
|
||||
FOREACH(MAFREAD_LINE ${MAFREAD_CONTENTS})
|
||||
# Test what this line is
|
||||
string(STRIP ${MAFREAD_LINE} MAFREAD_OLINE)
|
||||
string(SUBSTRING ${MAFREAD_OLINE} 0 1 MAFREAD_FIRST)
|
||||
#message("DEBUG: LINE='${MAFREAD_LINE}' FIRST='${MAFREAD_FIRST}'")
|
||||
|
||||
# The 'continue' command is cmake 3.2 - very late discovery
|
||||
if (MAFREAD_FIRST STREQUAL "")
|
||||
#message("DEBUG: ... skipped: empty")
|
||||
elseif (MAFREAD_FIRST STREQUAL "#")
|
||||
#message("DEBUG: ... skipped: comment")
|
||||
else()
|
||||
# Will be skipped if the line was a comment/empty
|
||||
string(REGEX MATCH "[ A-Z]" MAFREAD_SECMARK ${MAFREAD_FIRST})
|
||||
if (MAFREAD_SECMARK STREQUAL "")
|
||||
# This isn't a section, it's a list element.
|
||||
#message("DEBUG: ITEM: ${MAFREAD_OLINE} --> ${MAFREAD_VARIABLE}")
|
||||
LIST(APPEND ${MAFREAD_VARIABLE} ${MAFREAD_OLINE})
|
||||
else()
|
||||
# It's a section - change the running variable
|
||||
# Make it section name
|
||||
STRING(REPLACE " " "_" MAFREAD_SECNAME ${MAFREAD_OLINE})
|
||||
set(MAFREAD_VARIABLE ${MAFREAD_VAR_${MAFREAD_SECNAME}})
|
||||
if (MAFREAD_VARIABLE STREQUAL "")
|
||||
set(MAFREAD_VARIABLE MAFREAD_UNASSIGNED)
|
||||
endif()
|
||||
#message("DEBUG: NEW SECTION: '${MAFREAD_SECNAME}' --> VARIABLE: '${MAFREAD_VARIABLE}'")
|
||||
endif()
|
||||
endif()
|
||||
ENDFOREACH()
|
||||
|
||||
# Final debug report
|
||||
#set (ALL_VARS "")
|
||||
#message("DEBUG: extracted variables:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# list(APPEND ALL_VARS ${MAFREAD_VAR_${DEBUG_VAR}})
|
||||
#endforeach()
|
||||
#list(REMOVE_DUPLICATES ALL_VARS)
|
||||
#foreach(DEBUG_VAR ${ALL_VARS})
|
||||
# message("DEBUG: --> ${DEBUG_VAR} = ${${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
ENDMACRO(MafRead)
|
||||
|
||||
# New version of MafRead macro, which automatically adds directory
|
||||
# prefix. This should also resolve each relative path.
|
||||
# The directory specifies the location of maffile and
|
||||
# all files specified in the list.
|
||||
MACRO(MafReadDir directory maffile)
|
||||
# ARGN contains the extra "section-variable" pairs
|
||||
# If empty, return nothing
|
||||
|
@ -155,11 +80,11 @@ MACRO(MafReadDir directory maffile)
|
|||
configure_file(${directory}/${maffile} dummy_${maffile}.cmake.out)
|
||||
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/dummy_${maffile}.cmake.out)
|
||||
|
||||
#message("DEBUG: MAF FILE CONTENTS: ${MAFREAD_CONTENTS}")
|
||||
#message("DEBUG: PASSED VARIABLES:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# message("DEBUG: ${DEBUG_VAR}=${MAFREAD_VAR_${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
#message("DEBUG: MAF FILE CONTENTS: ${MAFREAD_CONTENTS}")
|
||||
#message("DEBUG: PASSED VARIABLES:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# message("DEBUG: ${DEBUG_VAR}=${MAFREAD_VAR_${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
|
||||
# The unnamed section becomes SOURCES
|
||||
set (MAFREAD_VARIABLE ${MAFREAD_VAR_SOURCES})
|
||||
|
@ -188,11 +113,60 @@ MACRO(MafReadDir directory maffile)
|
|||
if (${MAFREAD_SECTION_TYPE} STREQUAL file)
|
||||
get_filename_component(MAFREAD_OLINE ${directory}/${MAFREAD_OLINE} ABSOLUTE)
|
||||
endif()
|
||||
LIST(APPEND ${MAFREAD_VARIABLE} ${MAFREAD_OLINE})
|
||||
|
||||
set (MAFREAD_CONDITION_OK 1)
|
||||
if (DEFINED MAFREAD_CONDITION_LIST)
|
||||
FOREACH(MFITEM IN ITEMS ${MAFREAD_CONDITION_LIST})
|
||||
separate_arguments(MFITEM)
|
||||
FOREACH(MFVAR IN ITEMS ${MFITEM})
|
||||
STRING(SUBSTRING ${MFVAR} 0 1 MFPREFIX)
|
||||
if (MFPREFIX STREQUAL "!")
|
||||
STRING(SUBSTRING ${MFVAR} 1 -1 MFVAR)
|
||||
if (${MFVAR})
|
||||
set (MFCONDITION_RESULT 0)
|
||||
else()
|
||||
set (MFCONDITION_RESULT 1)
|
||||
endif()
|
||||
else()
|
||||
if (${MFVAR})
|
||||
set (MFCONDITION_RESULT 1)
|
||||
else()
|
||||
set (MFCONDITION_RESULT 0)
|
||||
endif()
|
||||
endif()
|
||||
#message("CONDITION: ${MFPREFIX} ${MFVAR} -> ${MFCONDITION_RESULT}")
|
||||
|
||||
MATH(EXPR MAFREAD_CONDITION_OK "${MAFREAD_CONDITION_OK} & (${MFCONDITION_RESULT})")
|
||||
ENDFOREACH()
|
||||
ENDFOREACH()
|
||||
endif()
|
||||
|
||||
if (MAFREAD_CONDITION_OK)
|
||||
LIST(APPEND ${MAFREAD_VARIABLE} ${MAFREAD_OLINE})
|
||||
else()
|
||||
#message("... NOT ADDED ITEM: ${MAFREAD_OLINE}")
|
||||
endif()
|
||||
else()
|
||||
# It's a section - change the running variable
|
||||
# It's a section
|
||||
# Check for conditionals (clear current conditions first)
|
||||
unset(MAFREAD_CONDITION_LIST)
|
||||
|
||||
STRING(FIND ${MAFREAD_OLINE} " -" MAFREAD_HAVE_CONDITION)
|
||||
if (NOT MAFREAD_HAVE_CONDITION EQUAL -1)
|
||||
# Cut off conditional specification, and
|
||||
# grab the section name and condition list
|
||||
STRING(REPLACE " -" ";" MAFREAD_CONDITION_LIST ${MAFREAD_OLINE})
|
||||
|
||||
#message("CONDITION READ: ${MAFREAD_CONDITION_LIST}")
|
||||
|
||||
LIST(GET MAFREAD_CONDITION_LIST 0 MAFREAD_OLINE)
|
||||
LIST(REMOVE_AT MAFREAD_CONDITION_LIST 0)
|
||||
#message("EXTRACTING SECTION=${MAFREAD_OLINE} CONDITIONS=${MAFREAD_CONDITION_LIST}")
|
||||
endif()
|
||||
# change the running variable
|
||||
# Make it section name
|
||||
STRING(REPLACE " " "_" MAFREAD_SECNAME ${MAFREAD_OLINE})
|
||||
#message("MAF SECTION: ${MAFREAD_SECNAME}")
|
||||
|
||||
# The cmake's version of 'if (MAFREAD_SECNAME[0] == '-')' - sigh...
|
||||
string(SUBSTRING ${MAFREAD_SECNAME} 0 1 MAFREAD_SECNAME0)
|
||||
|
@ -212,15 +186,15 @@ MACRO(MafReadDir directory maffile)
|
|||
ENDFOREACH()
|
||||
|
||||
# Final debug report
|
||||
#set (ALL_VARS "")
|
||||
#message("DEBUG: extracted variables:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# list(APPEND ALL_VARS ${MAFREAD_VAR_${DEBUG_VAR}})
|
||||
#endforeach()
|
||||
#list(REMOVE_DUPLICATES ALL_VARS)
|
||||
#foreach(DEBUG_VAR ${ALL_VARS})
|
||||
# message("DEBUG: --> ${DEBUG_VAR} = ${${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
#set (ALL_VARS "")
|
||||
#message("DEBUG: extracted variables:")
|
||||
#foreach(DEBUG_VAR ${MAFREAD_TAGS})
|
||||
# list(APPEND ALL_VARS ${MAFREAD_VAR_${DEBUG_VAR}})
|
||||
#endforeach()
|
||||
#list(REMOVE_DUPLICATES ALL_VARS)
|
||||
#foreach(DEBUG_VAR ${ALL_VARS})
|
||||
# message("DEBUG: --> ${DEBUG_VAR} = ${${DEBUG_VAR}}")
|
||||
#endforeach()
|
||||
ENDMACRO(MafReadDir)
|
||||
|
||||
# NOTE: This is historical only. Not in use.
|
||||
|
@ -240,9 +214,9 @@ MACRO(GetMafHeaders directory outvar)
|
|||
ENDMACRO(GetMafHeaders)
|
||||
|
||||
function (getVarsWith _prefix _varResult)
|
||||
get_cmake_property(_vars VARIABLES)
|
||||
string (REGEX MATCHALL "(^|;)${_prefix}[A-Za-z0-9_]*" _matchedVars "${_vars}")
|
||||
set (${_varResult} ${_matchedVars} PARENT_SCOPE)
|
||||
get_cmake_property(_vars VARIABLES)
|
||||
string (REGEX MATCHALL "(^|;)${_prefix}[A-Za-z0-9_]*" _matchedVars "${_vars}")
|
||||
set (${_varResult} ${_matchedVars} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function (check_testcode_compiles testcode libraries _successful)
|
||||
|
@ -254,15 +228,18 @@ function (check_testcode_compiles testcode libraries _successful)
|
|||
set (CMAKE_REQUIRED_LIBRARIES ${save_required_libraries})
|
||||
endfunction()
|
||||
|
||||
function (test_requires_clock_gettime _result)
|
||||
function (test_requires_clock_gettime _enable _linklib)
|
||||
# This function tests if clock_gettime can be used
|
||||
# - at all
|
||||
# - with or without librt
|
||||
|
||||
# Result will be:
|
||||
# rt (if librt required)
|
||||
# "" (if no extra libraries required)
|
||||
# -- killed by FATAL_ERROR if clock_gettime is not available
|
||||
# - CLOCK_MONOTONIC is available, link with librt:
|
||||
# _enable = ON; _linklib = "-lrt".
|
||||
# - CLOCK_MONOTONIC is available, link without librt:
|
||||
# _enable = ON; _linklib = "".
|
||||
# - CLOCK_MONOTONIC is not available:
|
||||
# _enable = OFF; _linklib = "-".
|
||||
|
||||
set (code "
|
||||
#include <time.h>
|
||||
|
@ -275,17 +252,39 @@ function (test_requires_clock_gettime _result)
|
|||
|
||||
check_testcode_compiles(${code} "" HAVE_CLOCK_GETTIME_IN)
|
||||
if (HAVE_CLOCK_GETTIME_IN)
|
||||
message(STATUS "Checked clock_gettime(): no extra libs needed")
|
||||
set (${_result} "" PARENT_SCOPE)
|
||||
message(STATUS "CLOCK_MONOTONIC: available, no extra libs needed")
|
||||
set (${_enable} ON PARENT_SCOPE)
|
||||
set (${_linklib} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
check_testcode_compiles(${code} "rt" HAVE_CLOCK_GETTIME_LIBRT)
|
||||
if (HAVE_CLOCK_GETTIME_LIBRT)
|
||||
message(STATUS "Checked clock_gettime(): requires -lrt")
|
||||
set (${_result} "-lrt" PARENT_SCOPE)
|
||||
message(STATUS "CLOCK_MONOTONIC: available, requires -lrt")
|
||||
set (${_enable} ON PARENT_SCOPE)
|
||||
set (${_linklib} "-lrt" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(FATAL_ERROR "clock_gettime() is not available on this system")
|
||||
set (${_enable} OFF PARENT_SCOPE)
|
||||
set (${_linklib} "-" PARENT_SCOPE)
|
||||
message(STATUS "CLOCK_MONOTONIC: not available on this system")
|
||||
endfunction()
|
||||
|
||||
function (parse_compiler_type wct _type _suffix)
|
||||
if (wct STREQUAL "")
|
||||
set(${_type} "" PARENT_SCOPE)
|
||||
set(${_suffix} "" PARENT_SCOPE)
|
||||
else()
|
||||
string(REPLACE "-" ";" OUTLIST ${wct})
|
||||
list(LENGTH OUTLIST OUTLEN)
|
||||
list(GET OUTLIST 0 ITEM)
|
||||
set(${_type} ${ITEM} PARENT_SCOPE)
|
||||
if (OUTLEN LESS 2)
|
||||
set(_suffix "" PARENT_SCOPE)
|
||||
else()
|
||||
list(GET OUTLIST 1 ITEM)
|
||||
set(${_suffix} "-${ITEM}" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
4
trunk/3rdparty/srt-1-fit/scripts/iOS.cmake
vendored
4
trunk/3rdparty/srt-1-fit/scripts/iOS.cmake
vendored
|
@ -151,10 +151,10 @@ if (NOT DEFINED IOS_ARCH)
|
|||
set (IOS_ARCH x86_64)
|
||||
endif (${IOS_PLATFORM} STREQUAL OS)
|
||||
endif(NOT DEFINED IOS_ARCH)
|
||||
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS")
|
||||
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS")
|
||||
|
||||
# Set the find root to the iOS developer roots and to user defined paths
|
||||
set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root")
|
||||
set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root")
|
||||
|
||||
# default to searching for frameworks first
|
||||
set (CMAKE_FIND_FRAMEWORK FIRST)
|
||||
|
|
38
trunk/3rdparty/srt-1-fit/scripts/maf.vim
vendored
Normal file
38
trunk/3rdparty/srt-1-fit/scripts/maf.vim
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
"
|
||||
" SRT - Secure, Reliable, Transport
|
||||
" Copyright (c) 2020 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/.
|
||||
"
|
||||
" This file describes MAF ("manifest") file syntax used by
|
||||
" SRT project.
|
||||
"
|
||||
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" conditionals
|
||||
syn match mafCondition contained " - [!A-Za-z].*"hs=s+2
|
||||
|
||||
" section
|
||||
syn match mafSection "^[A-Z][0-9A-Za-z_].*$" contains=mafCondition
|
||||
syn match mafsection "^ .*$" contains=mafCondition
|
||||
|
||||
" comments
|
||||
syn match mafComment "^\s*\zs#.*$"
|
||||
syn match mafComment "\s\zs#.*$"
|
||||
syn match mafComment contained "#.*$"
|
||||
|
||||
|
||||
" hilites
|
||||
|
||||
hi def link mafComment Comment
|
||||
hi def link mafSection Statement
|
||||
hi def link mafCondition Number
|
||||
|
||||
|
||||
let b:current_syntax = "maf"
|
27
trunk/3rdparty/srt-1-fit/scripts/release-notes/README.md
vendored
Normal file
27
trunk/3rdparty/srt-1-fit/scripts/release-notes/README.md
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Script Description
|
||||
|
||||
Script designed to generate release notes template with main sections, contributors list, and detailed changelog out of `.csv` SRT git log file. The output `release-notes.md` file is generated in the root folder.
|
||||
|
||||
In order to obtain the git log file since the previous release (e.g., v1.4.0), use the following command:
|
||||
|
||||
```shell
|
||||
git log --pretty=format:"%h|%s|%an|%ae" v1.4.0...HEAD > commits.csv
|
||||
```
|
||||
|
||||
Use the produced `commits.csv` file as an input to the script:
|
||||
|
||||
```shell
|
||||
python scripts/release-notes/generate-release-notes.py commits.csv
|
||||
```
|
||||
|
||||
The script produces `release-notes.md` as an output.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
* Python 3.6+
|
||||
|
||||
To install Python libraries use:
|
||||
```shell
|
||||
pip install -r requirements.txt
|
||||
```
|
120
trunk/3rdparty/srt-1-fit/scripts/release-notes/generate_release_notes.py
vendored
Normal file
120
trunk/3rdparty/srt-1-fit/scripts/release-notes/generate_release_notes.py
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
import enum
|
||||
|
||||
import click
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
|
||||
@enum.unique
|
||||
class Area(enum.Enum):
|
||||
core = 'core'
|
||||
tests = 'tests'
|
||||
build = 'build'
|
||||
apps = 'apps'
|
||||
docs = 'docs'
|
||||
|
||||
|
||||
def define_area(msg):
|
||||
areas = [e.value for e in Area]
|
||||
|
||||
for area in areas:
|
||||
if msg.startswith(f'[{area}] '):
|
||||
return area
|
||||
|
||||
return np.NaN
|
||||
|
||||
|
||||
def delete_prefix(msg):
|
||||
prefixes = [f'[{e.value}] ' for e in Area]
|
||||
|
||||
for prefix in prefixes:
|
||||
if msg.startswith(prefix):
|
||||
return msg[len(prefix):]
|
||||
|
||||
return msg[:]
|
||||
|
||||
|
||||
def write_into_changelog(df, f):
|
||||
f.write('\n')
|
||||
for _, row in df.iterrows():
|
||||
f.write(f"\n{row['commit']} {row['message']}")
|
||||
f.write('\n')
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument(
|
||||
'git_log',
|
||||
type=click.Path(exists=True)
|
||||
)
|
||||
def main(git_log):
|
||||
"""
|
||||
Script designed to generate release notes template with main sections,
|
||||
contributors list, and detailed changelog out of .csv SRT git log file.
|
||||
"""
|
||||
df = pd.read_csv(git_log, sep = '|', names = ['commit', 'message', 'author', 'email'])
|
||||
df['area'] = df['message'].apply(define_area)
|
||||
df['message'] = df['message'].apply(delete_prefix)
|
||||
|
||||
# Split commits by areas
|
||||
core = df[df['area']==Area.core.value]
|
||||
tests = df[df['area']==Area.tests.value]
|
||||
build = df[df['area']==Area.build.value]
|
||||
apps = df[df['area']==Area.apps.value]
|
||||
docs = df[df['area']==Area.docs.value]
|
||||
other = df[df['area'].isna()]
|
||||
|
||||
# Define individual contributors
|
||||
contributors = df.groupby(['author', 'email'])
|
||||
contributors = list(contributors.groups.keys())
|
||||
|
||||
with open('release-notes.md', 'w') as f:
|
||||
f.write('# Release Notes\n')
|
||||
|
||||
f.write('\n## API / ABI / Integration Changes\n')
|
||||
f.write('\n**API/ABI version: 1.x.**\n')
|
||||
|
||||
f.write('\n## New Features and Improvements\n')
|
||||
f.write('\n## Important Bug Fixes\n')
|
||||
f.write('\n## Build\n')
|
||||
f.write('\n## Documentation\n')
|
||||
|
||||
f.write('\n## Contributors\n')
|
||||
for name, email in contributors:
|
||||
f.write(f'\n{name} <{email}>')
|
||||
f.write('\n')
|
||||
|
||||
f.write('\n## Changelog\n')
|
||||
f.write('\n<details><summary>Click to expand/collapse</summary>')
|
||||
f.write('\n<p>')
|
||||
f.write('\n')
|
||||
|
||||
if not core.empty:
|
||||
f.write('\n### Core Functionality')
|
||||
write_into_changelog(core, f)
|
||||
|
||||
if not tests.empty:
|
||||
f.write('\n### Unit Tests')
|
||||
write_into_changelog(tests, f)
|
||||
|
||||
if not build.empty:
|
||||
f.write('\n### Build Scripts (CMake, etc.)')
|
||||
write_into_changelog(build, f)
|
||||
|
||||
if not apps.empty:
|
||||
f.write('\n### Sample Applications')
|
||||
write_into_changelog(apps, f)
|
||||
|
||||
if not docs.empty:
|
||||
f.write('\n### Documentation')
|
||||
write_into_changelog(docs, f)
|
||||
|
||||
if not other.empty:
|
||||
f.write('\n### Other')
|
||||
write_into_changelog(other, f)
|
||||
|
||||
f.write('\n</p>')
|
||||
f.write('\n</details>')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
3
trunk/3rdparty/srt-1-fit/scripts/release-notes/requirements.txt
vendored
Normal file
3
trunk/3rdparty/srt-1-fit/scripts/release-notes/requirements.txt
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
click>=7.1.2
|
||||
numpy>=1.19.1
|
||||
pandas>=0.25.3
|
|
@ -27,13 +27,22 @@ if($Env:APPVEYOR){
|
|||
Update-AppveyorBuild -Version "$majorVer.$minorVer.$patchVer.$buildNum"
|
||||
$FileDescriptionBranchCommitValue = "$Env:APPVEYOR_REPO_NAME - $($Env:APPVEYOR_REPO_BRANCH) ($($Env:APPVEYOR_REPO_COMMIT.substring(0,8)))"
|
||||
}
|
||||
if($Env:TEAMCITY_VERSION){
|
||||
#make TeamCity update with this new version number
|
||||
Write-Output "##teamcity[buildNumber '$majorVer.$minorVer.$patchVer.$buildNum']"
|
||||
Write-Output "##teamcity[setParameter name='MajorVersion' value='$majorVer']"
|
||||
Write-Output "##teamcity[setParameter name='MinorVersion' value='$minorVer']"
|
||||
Write-Output "##teamcity[setParameter name='PatchVersion' value='$patchVer']"
|
||||
Write-Output "##teamcity[setParameter name='BuildVersion' value='$buildNum']"
|
||||
$FileDescriptionBranchCommitValue = "$majorVer.$minorVer.$patchVer.$buildNum - ($($Env:BUILD_VCS_NUMBER.substring(0,8)))"
|
||||
}
|
||||
|
||||
#find C++ resource files and update file description with branch / commit details
|
||||
$FileDescriptionStringRegex = '(\bVALUE\s+\"FileDescription\"\s*\,\s*\")([^\"]*\\\")*[^\"]*(\")'
|
||||
|
||||
Get-ChildItem -Path "./srtcore/srt_shared.rc" | ForEach-Object {
|
||||
Get-ChildItem -Path "../srtcore/srt_shared.rc" | ForEach-Object {
|
||||
$fileName = $_
|
||||
Write-Host "Processing metadata changes for file: $fileName"
|
||||
Write-Output "Processing metadata changes for file: $fileName"
|
||||
|
||||
$FileLines = Get-Content -path $fileName
|
||||
|
||||
|
|
938
trunk/3rdparty/srt-1-fit/scripts/srt-dev.lua
vendored
Normal file
938
trunk/3rdparty/srt-1-fit/scripts/srt-dev.lua
vendored
Normal file
|
@ -0,0 +1,938 @@
|
|||
-- @brief srt-dev Protocol dissector plugin
|
||||
|
||||
-- create a new dissector
|
||||
local NAME = "SRT-dev"
|
||||
local srt_dev = Proto(NAME, "SRT-dev Protocol")
|
||||
|
||||
-- create a preference of a Protocol
|
||||
srt_dev.prefs["srt_udp_port"] = Pref.uint("SRT UDP Port", 1935, "SRT UDP Port")
|
||||
|
||||
-- create fields of srt_dev
|
||||
-- Base.HEX, Base.DEC, Base.OCT, Base.UNIT_STRING, Base.NONE
|
||||
local fields = srt_dev.fields
|
||||
-- General field
|
||||
local pack_type_select = {
|
||||
[0] = "Data Packet",
|
||||
[1] = "Control Packet"
|
||||
}
|
||||
fields.pack_type_tree = ProtoField.uint32(NAME .. ".pack_type_tree", "Packet Type", base.HEX)
|
||||
fields.pack_type = ProtoField.uint16("srt_dev.pack_type", "Packet Type", base.HEX, pack_type_select, 0x8000)
|
||||
fields.reserve = ProtoField.uint16("srt_dev.reserve", "Reserve", base.DEC)
|
||||
fields.additional_info = ProtoField.uint32("srt_dev.additional_info", "Additional Information", base.DEC)
|
||||
fields.time_stamp = ProtoField.uint32("srt_dev.time_stamp", "Time Stamp", base.DEC)
|
||||
fields.dst_sock = ProtoField.uint32("srt_dev.dst_sock", "Destination Socket ID", base.DEC)
|
||||
fields.none = ProtoField.none("srt_dev.none", "none", base.NONE)
|
||||
|
||||
-- Data packet fields
|
||||
fields.data_flag_info_tree = ProtoField.uint8("srt_dev.data_flag_info_tree", "Data Flag Info", base.HEX)
|
||||
local FF_state_select = {
|
||||
[0] = "[Middle packet]",
|
||||
[1] = "[Last packet]",
|
||||
[2] = "[First packet]",
|
||||
[3] = "[Single packet]"
|
||||
}
|
||||
fields.FF_state = ProtoField.uint8("srt_dev.FF_state", "FF state", base.HEX, FF_state_select, 0xC0)
|
||||
local O_state_select = {
|
||||
[0] = "[ORD_RELAX]",
|
||||
[1] = "[ORD_REQUIRED]"
|
||||
}
|
||||
fields.O_state = ProtoField.uint8("srt_dev.O_state", "O state", base.HEX, O_state_select, 0x20)
|
||||
local KK_state_select = {
|
||||
[0] = "[Not encrypted]",
|
||||
[1] = "[Data encrypted with even key]",
|
||||
[2] = "[Data encrypted with odd key]"
|
||||
}
|
||||
fields.KK_state = ProtoField.uint8("srt_dev.KK_state", "KK state", base.HEX, KK_state_select, 0x18)
|
||||
local R_state_select = {
|
||||
[0] = "[ORIGINAL]",
|
||||
[1] = "[RETRANSMITTED]"
|
||||
}
|
||||
fields.R_state = ProtoField.uint8("srt_dev.R_state", "R state", base.HEX, R_state_select, 0x04)
|
||||
fields.seq_num = ProtoField.uint32("srt_dev.seq_num", "Sequence Number", base.DEC)
|
||||
fields.msg_num = ProtoField.uint32("srt_dev.msg_num", "Message Number", base.DEC)--, nil, 0x3FFFFFF)
|
||||
|
||||
-- control packet fields
|
||||
local msg_type_select = {
|
||||
[0] = "[HANDSHAKE]",
|
||||
[1] = "[KEEPALIVE]",
|
||||
[2] = "[ACK]",
|
||||
[3] = "[NAK(Loss Report)]",
|
||||
[4] = "[Congestion Warning]",
|
||||
[5] = "[Shutdown]",
|
||||
[6] = "[ACKACK]",
|
||||
[7] = "[Drop Request]",
|
||||
[8] = "[Peer Error]",
|
||||
[0x7FFF] = "[Message Extension Type]"
|
||||
}
|
||||
fields.msg_type = ProtoField.uint16("srt_dev.msg_type", "Message Type", base.HEX, msg_type_select, 0x7FFF)
|
||||
fields.msg_ext_type = ProtoField.uint16("srt_dev.msg_ext_type", "Message Extented Type", base.DEC)
|
||||
|
||||
local flag_state_select = {
|
||||
[0] = "Unset",
|
||||
[1] = "Set"
|
||||
}
|
||||
|
||||
-- Handshake packet fields
|
||||
fields.UDT_version = ProtoField.uint32("srt_dev.UDT_version", "UDT Version", base.DEC)
|
||||
fields.sock_type = ProtoField.uint32("srt_dev.sock_type", "Socket Type", base.DEC)
|
||||
fields.ency_fld = ProtoField.uint16("srt_dev.ency_fld", "Encryption Field", base.DEC)
|
||||
fields.ext_fld = ProtoField.uint16("srt_dev.ext_fld", "Extension Fields", base.HEX)
|
||||
fields.ext_fld_tree = ProtoField.uint16("srt_dev.ext_fld_tree", "Extension Fields Tree", base.HEX)
|
||||
fields.hsreq = ProtoField.uint16("srt_dev.hsreq", "HS_EXT_HSREQ", base.HEX, flag_state_select, 0x1)
|
||||
fields.kmreq = ProtoField.uint16("srt_dev.kmreq", "HS_EXT_KMREQ", base.HEX, flag_state_select, 0x2)
|
||||
fields.config = ProtoField.uint16("srt_dev.config", "HS_EXT_CONFIG", base.HEX, flag_state_select, 0x4)
|
||||
fields.isn = ProtoField.uint32("srt_dev.isn", "Initial packet sequence number", base.DEC)
|
||||
fields.mss = ProtoField.uint32("srt_dev.mss", "Max Packet Size", base.DEC)
|
||||
fields.fc = ProtoField.uint32("srt_dev.fc", "Maximum Flow Window Size", base.DEC)
|
||||
fields.conn_type = ProtoField.int32("srt_dev.conn_type", "Connection Type", base.DEC)
|
||||
fields.sock_id = ProtoField.uint32("srt_dev.sock_id", "Socket ID", base.DEC)
|
||||
fields.syn_cookie = ProtoField.uint32("srt_dev.syn_cookie", "SYN cookie", base.DEC)
|
||||
fields.peer_ipaddr = ProtoField.none("srt_dev.peer_ipaddr", "Peer IP address", base.NONE)
|
||||
fields.peer_ipaddr_4 = ProtoField.ipv4("srt_dev.peer_ipaddr", "Peer IP address")
|
||||
fields.peer_ipaddr_6 = ProtoField.ipv6("srt_dev.peer_ipaddr", "Peer IP address")
|
||||
local ext_type_select = {
|
||||
[-1] = "SRT_CMD_NONE",
|
||||
[0] = "SRT_CMD_REJECT",
|
||||
[1] = "SRT_CMD_HSREQ",
|
||||
[2] = "SRT_CMD_HSRSP",
|
||||
[3] = "SRT_CMD_KMREQ",
|
||||
[4] = "SRT_CMD_KMRSP",
|
||||
[5] = "SRT_CMD_SID",
|
||||
[6] = "SRT_CMD_CONGESTION",
|
||||
[7] = "SRT_CMD_FILTER",
|
||||
[8] = "SRT_CMD_GROUP"
|
||||
}
|
||||
fields.ext_type_msg_tree = ProtoField.none("srt_dev.ext_type", "Extension Type Message", base.NONE)
|
||||
fields.ext_type = ProtoField.uint16("srt_dev.ext_type", "Extension Type", base.HEX, ext_type_select, 0xF)
|
||||
fields.ext_size = ProtoField.uint16("srt_dev.ext_size", "Extension Size", base.DEC)
|
||||
|
||||
-- Handshake packet, ext type == SRT_CMD_HSREQ or SRT_CMD_HSRSP field
|
||||
fields.srt_version = ProtoField.uint32("srt_dev.srt_version", "SRT Version", base.HEX)
|
||||
fields.srt_flags = ProtoField.uint32("srt_dev.srt_flags", "SRT Flags", base.HEX)
|
||||
fields.tsbpb_resv = ProtoField.uint16("srt_dev.tsbpb_resv", "TsbPb Receive", base.DEC)
|
||||
fields.tsbpb_delay = ProtoField.uint16("srt_dev.tsbpb_delay", "TsbPb Delay", base.DEC)
|
||||
fields.tsbpd_delay = ProtoField.uint16("srt_dev.tsbpd_delay", "TsbPd Delay", base.DEC)
|
||||
fields.rcv_tsbpd_delay = ProtoField.uint16("srt_dev.rcv_tsbpd_delay", "Receiver TsbPd Delay", base.DEC)
|
||||
fields.snd_tsbpd_delay = ProtoField.uint16("srt_dev.snd_tsbpd_delay", "Sender TsbPd Delay", base.DEC)
|
||||
|
||||
-- V and PT status flag
|
||||
local V_state_select = {
|
||||
[1] = "Initial version"
|
||||
}
|
||||
fields.V_state = ProtoField.uint8("srt_dev.V_state", "V", base.HEX, V_state_select, 0x70)
|
||||
local PT_state_select = {
|
||||
[0] = "Reserved",
|
||||
[1] = "MSmsg",
|
||||
[2] = "KMmsg",
|
||||
[7] = "Reserved to discriminate MPEG-TS packet(0x47=sync byte)"
|
||||
}
|
||||
fields.PT_state = ProtoField.uint8("srt_dev.PT_state", "PT", base.HEX, state_table, 0xF)
|
||||
fields.sign = ProtoField.uint16("srt_dev.sign", "Signature", base.HEX)
|
||||
local resv_select = {
|
||||
[0] = "Reserved for flag extension or other usage"
|
||||
}
|
||||
fields.resv = ProtoField.uint8("srt_dev.resv", "Resv", base.DEC, state_table, 0xFC)
|
||||
fields.ext_KK_state = ProtoField.uint8("srt_dev.ext_KK_state", "KK_state", base.HEX, KK_state_select, 0x3)
|
||||
fields.KEKI = ProtoField.uint32("srt_dev.KEKI", "KEKI", base.DEC)
|
||||
fields.cipher = ProtoField.uint8("srt_dev.cipher", "Cipher", base.DEC)
|
||||
fields.auth = ProtoField.uint8("srt_dev.auth", "auth", base.DEC)
|
||||
fields.SE = ProtoField.uint8("srt_dev.SE", "SE", base.DEC)
|
||||
fields.resv1 = ProtoField.uint8("srt_dev.resv1", "resv1", base.DEC)
|
||||
fields.resv2 = ProtoField.uint16("srt_dev.resv2", "resv2", base.DEC)
|
||||
fields.slen = ProtoField.uint8("srt_dev.slen", "Salt length(bytes)/4", base.DEC)
|
||||
fields.klen = ProtoField.uint8("srt_dev.klen", "SEK length(bytes)/4", base.DEC)
|
||||
fields.salt = ProtoField.uint32("srt_dev.salt", "Salt key", base.DEC)
|
||||
fields.wrap = ProtoField.none("srt_dev.wrap", "Wrap key(s)", base.NONE)
|
||||
|
||||
-- Wrap Field
|
||||
fields.ICV = ProtoField.uint64("srt_dev.ICV", "Integerity Check Vector", base.HEX)
|
||||
fields.odd_key = ProtoField.stringz("srt_dev.odd_key", "Odd key", base.ASCII)
|
||||
fields.even_key = ProtoField.stringz("srt_dev.even_key", "Even key", base.ASCII)
|
||||
|
||||
-- ext_type == SRT_CMD_SID field
|
||||
fields.sid = ProtoField.string("srt_dev.sid", "Stream ID", base.ASCII)
|
||||
-- ext_type == SRT_CMD_CONGESTION field
|
||||
fields.congestion = ProtoField.string("srt_dev.congestion", "Congestion Controller", base.ASCII)
|
||||
-- ext_type == SRT_CMD_FILTER field
|
||||
fields.filter = ProtoField.string("srt_dev.filter", "Filter", base.ASCII)
|
||||
-- ext_type == SRT_CMD_GROUP field
|
||||
fields.group = ProtoField.string("srt_dev.group", "Group Data", base.ASCII)
|
||||
|
||||
-- SRT flags
|
||||
fields.srt_opt_tsbpdsnd = ProtoField.uint32("srt_dev.srt_opt_tsbpdsnd", "SRT_OPT_TSBPDSND", base.HEX, flag_state_select, 0x1)
|
||||
fields.srt_opt_tsbpdrcv = ProtoField.uint32("srt_dev.srt_opt_tsbpdrcv", "SRT_OPT_TSBPDRCV", base.HEX, flag_state_select, 0x2)
|
||||
fields.srt_opt_haicrypt = ProtoField.uint32("srt_dev.srt_opt_haicrypt", "SRT_OPT_HAICRYPT", base.HEX, flag_state_select, 0x4)
|
||||
fields.srt_opt_tlpktdrop = ProtoField.uint32("srt_dev.srt_opt_tlpktdrop", "SRT_OPT_TLPKTDROP", base.HEX, flag_state_select, 0x8)
|
||||
fields.srt_opt_nakreport = ProtoField.uint32("srt_dev.srt_opt_nakreport", "SRT_OPT_NAKREPORT", base.HEX, flag_state_select, 0x10)
|
||||
fields.srt_opt_rexmitflg = ProtoField.uint32("srt_dev.srt_opt_rexmitflg", "SRT_OPT_REXMITFLG", base.HEX, flag_state_select, 0x20)
|
||||
fields.srt_opt_stream = ProtoField.uint32("srt_dev.srt_opt_stream", "SRT_OPT_STREAM", base.HEX, flag_state_select, 0x40)
|
||||
|
||||
-- ACK fields
|
||||
fields.last_ack_pack = ProtoField.uint32("srt_dev.last_ack_pack", "Last ACK Packet Sequence Number", base.DEC)
|
||||
fields.rtt = ProtoField.int32("srt_dev.rtt", "Round Trip Time", base.DEC)
|
||||
fields.rtt_variance = ProtoField.int32("srt_dev.rtt_variance", "Round Trip Time Variance", base.DEC)
|
||||
fields.buf_size = ProtoField.uint32("srt_dev.buf_size", "Available Buffer Size", base.DEC)
|
||||
fields.pack_rcv_rate = ProtoField.uint32("srt_dev.pack_rcv_rate", "Packet Receiving Rate", base.DEC)
|
||||
fields.est_link_capacity = ProtoField.uint32("srt_dev.est_link_capacity", "Estimated Link Capacity", base.DEC)
|
||||
fields.rcv_rate = ProtoField.uint32("srt_dev.rcv_rate", "Receiving Rate", base.DEC)
|
||||
|
||||
-- ACKACK fields
|
||||
fields.ack_num = ProtoField.uint32("srt_dev.ack_num", "ACK number", base.DEC)
|
||||
fields.ctl_info = ProtoField.uint32("srt_dev.ctl_info", "Control Information", base.DEC)
|
||||
|
||||
-- KMRSP fields
|
||||
local srt_km_state_select = {
|
||||
[0] = "[SRT_KM_UNSECURED]",
|
||||
[1] = "[SRT_KM_SECURING]",
|
||||
[2] = "[SRT_KM_SECURED]",
|
||||
[3] = "[SRT_KM_NOSECRET]",
|
||||
[4] = "[SRT_KM_BADSECRET]"
|
||||
}
|
||||
fields.km_err = ProtoField.uint32("srt_dev.km_err", "Key Message Error", base.HEX, srt_km_state_select, 0xF)
|
||||
|
||||
-- NAK Control Packet fields
|
||||
fields.lost_list_tree = ProtoField.none("srt_dev.lost_list_tree", "Lost Packet List", base.NONE)
|
||||
fields.lost_pack_seq = ProtoField.uint32("srt_dev.lost_pack_seq", "Lost Packet Sequence Number", base.DEC)
|
||||
fields.lost_pack_range_tree = ProtoField.none("srt_dev.lost_pack_range_tree", "Lost Packet Range", base.NONE)
|
||||
fields.lost_start = ProtoField.uint32("srt_dev.lost_start", "Lost Starting Sequence", base.DEC)
|
||||
fields.lost_up_to = ProtoField.uint32("srt_dev.lost_up_to", "Lost Up To(including)", base.DEC)
|
||||
|
||||
-- Dissect packet
|
||||
function srt_dev.dissector (tvb, pinfo, tree)
|
||||
-- Packet is based on UDP, so the data can be processed directly after UDP
|
||||
local subtree = tree:add(srt_dev, tvb())
|
||||
local offset = 0
|
||||
|
||||
-- Changes the protocol name
|
||||
pinfo.cols.protocol = srt_dev.name
|
||||
|
||||
-- Take out the first bit of package
|
||||
-- 0 -> Data Packet
|
||||
-- 1 -> Control Packet
|
||||
local typebit = bit.rshift(tvb(offset, 1):uint(), 7)
|
||||
pack_type_tree = subtree:add(fields.pack_type_tree, tvb(offset, 4))
|
||||
|
||||
if typebit == 1 then
|
||||
-- Handle Control Packet
|
||||
pack_type_tree:add(fields.pack_type, tvb(offset, 2))
|
||||
|
||||
local msg_type = tvb(offset, 2):uint()
|
||||
if msg_type ~= 0xFFFF then
|
||||
-- If type field isn't '0x7FFF',it means packet is normal data packet, then handle type field
|
||||
msg_type = bit.band(msg_type, 0x7FFF)
|
||||
|
||||
function parse_three_param()
|
||||
-- Ignore Additional Info (this field is not defined in this packet type)
|
||||
subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Time Stamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Destination Socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
end
|
||||
|
||||
local switch = {
|
||||
[0] = function()
|
||||
pinfo.cols.info:append(" [HANDSHAKE]")
|
||||
pack_type_tree:append_text(" [HANDSHAKE]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Additional Info, Timestamp and Destination Socket
|
||||
parse_three_param()
|
||||
|
||||
-- Handle UDT version field
|
||||
local UDT_version = tvb(offset, 4):uint()
|
||||
subtree:add(fields.UDT_version, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
if UDT_version == 4 then
|
||||
-- UDT version is 4, packet is different from UDT version 5
|
||||
-- Handle sock type
|
||||
local sock_type = tvb(offset, 4):uint()
|
||||
if sock_type == 1 then
|
||||
subtree:add(fields.sock_type, tvb(offset, 4)):append_text(" [SRT_STREAM]")
|
||||
elseif sock_type == 2 then
|
||||
subtree:add(fields.sock_type, tvb(offset, 4)):append_text(" [SRT_DRAGAM]")
|
||||
end
|
||||
offset = offset + 4
|
||||
elseif UDT_version == 5 then
|
||||
-- Handle Encryption Field
|
||||
local encr_fld = tvb(offset, 2):int()
|
||||
if encr_fld == 0 then
|
||||
subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (PBKEYLEN not advertised)")
|
||||
elseif encr_fld == 2 then
|
||||
subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-128)")
|
||||
elseif encr_fld == 3 then
|
||||
subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-192)")
|
||||
else
|
||||
subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-256)")
|
||||
end
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Extension Field
|
||||
local ext_fld = tvb(offset, 2):int()
|
||||
if ext_fld == 0x4A17 then
|
||||
subtree:add(fields.ext_fld, tvb(offset, 2)):append_text(" [HSv5 MAGIC]")
|
||||
else
|
||||
-- Extension Field is HS_EXT_prefix
|
||||
-- The define is in fiel handshake.h
|
||||
local ext_fld_tree = subtree:add(fields.ext_fld_tree, tvb(offset, 2))
|
||||
local str_table = { " [" }
|
||||
ext_fld_tree:add(fields.hsreq, tvb(offset, 2))
|
||||
if bit.band(tvb(offset, 2):uint(), 0x1) == 1 then
|
||||
table.insert(str_table, "HS_EXT_HSREQ")
|
||||
table.insert(str_table, " | ")
|
||||
end
|
||||
ext_fld_tree:add(fields.kmreq, tvb(offset, 2)):append_text(" [HS_EXT_KMREQ]")
|
||||
if bit.band(tvb(offset, 2):uint(), 0x2) == 2 then
|
||||
table.insert(str_table, "HS_EXT_KMREQ")
|
||||
table.insert(str_table, " | ")
|
||||
end
|
||||
ext_fld_tree:add(fields.config, tvb(offset, 2)):append_text(" [HS_EXT_CONFIG]")
|
||||
if bit.band(tvb(offset, 2):uint(), 0x4) == 4 then
|
||||
table.insert(str_table, "HS_EXT_CONFIG")
|
||||
table.insert(str_table, " | ")
|
||||
end
|
||||
table.remove(str_table)
|
||||
table.insert(str_table, "]")
|
||||
if ext_fld ~= 0 then
|
||||
ext_fld_tree:append_text(table.concat(str_table))
|
||||
end
|
||||
end
|
||||
offset = offset + 2
|
||||
end
|
||||
|
||||
-- Handle Initial packet sequence number
|
||||
subtree:add(fields.isn, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Maximum Packet Size
|
||||
subtree:add(fields.mss, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Maximum Flow Window Size
|
||||
subtree:add(fields.fc, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Connection Type
|
||||
local conn_type = tvb(offset, 4):int()
|
||||
local conn_type_tree = subtree:add(fields.conn_type, tvb(offset, 4))
|
||||
if conn_type == 0 then
|
||||
conn_type_tree:append_text(" [WAVEAHAND] (Rendezvous Mode)")
|
||||
pinfo.cols.info:append(" [WAVEAHAND] (Rendezvous Mode)")
|
||||
elseif conn_type == 1 then
|
||||
conn_type_tree:append_text(" [INDUCTION]")
|
||||
elseif conn_type == -1 then
|
||||
conn_type_tree:append_text(" [CONCLUSION]")
|
||||
elseif conn_type == -2 then
|
||||
conn_type_tree:append_text(" [AGREEMENT] (Rendezvous Mode)")
|
||||
pinfo.cols.info:append(" [AGREEMENT] (Rendezvous Mode)")
|
||||
end
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Socket ID
|
||||
subtree:add(fields.sock_id, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle SYN cookie
|
||||
local syn_cookie = tvb(offset, 4):int()
|
||||
subtree:add(fields.syn_cookie, tvb(offset, 4))
|
||||
if syn_cookie == 0 then
|
||||
conn_type_tree:append_text(" (Caller to Listener)")
|
||||
pinfo.cols.info:append(" (Caller to Listener)")
|
||||
else
|
||||
if conn_type == 1 then
|
||||
-- reports cookie from listener
|
||||
conn_type_tree:append_text(" (Listener to Caller)")
|
||||
pinfo.cols.info:append(" (Listener to Caller)")
|
||||
end
|
||||
end
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Peer IP address
|
||||
-- Note the network byte order
|
||||
local the_last_96_bits = 0
|
||||
the_last_96_bits = the_last_96_bits + math.floor(tvb(offset + 4, 4):int() * (2 ^ 16))
|
||||
the_last_96_bits = the_last_96_bits + math.floor(tvb(offset + 8, 4):int() * (2 ^ 8))
|
||||
the_last_96_bits = the_last_96_bits + tvb(offset + 12, 4):int()
|
||||
if the_last_96_bits == 0 then
|
||||
subtree:add_le(fields.peer_ipaddr_4, tvb(offset, 4))
|
||||
else
|
||||
subtree:add_le(fields.peer_ipaddr, tvb(offset, 16))
|
||||
end
|
||||
|
||||
offset = offset + 16
|
||||
|
||||
-- UDT version is 4, packet handle finish
|
||||
if UDT_version == 4 or offset == tvb:len() then
|
||||
return
|
||||
end
|
||||
|
||||
function process_ext_type()
|
||||
-- Handle Ext Type, processing by type
|
||||
local ext_type = tvb(offset, 2):int()
|
||||
if ext_type == 1 or ext_type == 2 then
|
||||
local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, 16))
|
||||
if ext_type == 1 then
|
||||
ext_type_msg_tree:append_text(" [SRT_CMD_HSREQ]")
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
conn_type_tree:append_text(" (Caller to Listener)")
|
||||
pinfo.cols.info:append(" (Caller to Listener)")
|
||||
else
|
||||
ext_type_msg_tree:append_text(" [SRT_CMD_HSRSP]")
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
conn_type_tree:append_text(" (Listener to Caller)")
|
||||
pinfo.cols.info:append(" (Listener to Caller)")
|
||||
end
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Ext Size
|
||||
ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle SRT Version
|
||||
ext_type_msg_tree:add(fields.srt_version, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle SRT Flags
|
||||
local SRT_flags_tree = ext_type_msg_tree:add(fields.srt_flags, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tsbpdsnd, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tsbpdrcv, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_haicrypt, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tlpktdrop, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_nakreport, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_rexmitflg, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_stream, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Recv TsbPd Delay and Snd TsbPd Delay
|
||||
if UDT_version == 4 then
|
||||
ext_type_msg_tree:add(fields.tsbpd_delay, tvb(offset, 2)):append_text(" [Unused in HSv4]")
|
||||
offset = offset + 2
|
||||
ext_type_msg_tree:add(fields.tsbpb_delay, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
else
|
||||
ext_type_msg_tree:add(fields.rcv_tsbpd_delay, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
ext_type_msg_tree:add(fields.snd_tsbpd_delay, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
end
|
||||
elseif ext_type == 3 or ext_type == 4 then
|
||||
local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, 16))
|
||||
if ext_type == 3 then
|
||||
ext_type_msg_tree:append_text(" [SRT_CMD_KMREQ]")
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
conn_type_tree:append_text(" (Listener to Caller)")
|
||||
else
|
||||
ext_type_msg_tree:append_text(" [SRT_CMD_KMRSP]")
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
end
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Ext Size
|
||||
local km_len = tvb(offset, 2):uint()
|
||||
ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2)):append_text(" (byte/4)")
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle SRT_CMD_KMREQ message
|
||||
-- V and PT status flag
|
||||
ext_type_msg_tree:add(fields.V_state, tvb(offset, 1))
|
||||
ext_type_msg_tree:add(fields.PT_state, tvb(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle sign
|
||||
ext_type_msg_tree:add(fields.sign, tvb(offset, 2)):append_text(" (/'HAI/' PnP Vendor ID in big endian order)")
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle resv
|
||||
ext_type_msg_tree:add(fields.resv, tvb(offset, 1))
|
||||
|
||||
-- Handle KK flag
|
||||
local KK = tvb(offset, 1):uint()
|
||||
ext_type_msg_tree:add(fields.ext_KK_state, tvb(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle KEKI
|
||||
if tvb(offset, 4):uint() == 0 then
|
||||
ext_type_msg_tree:add(fields.KEKI, tvb(offset, 4)):append_text(" (Default stream associated key(stream/system default))")
|
||||
else
|
||||
ext_type_msg_tree:add(fields.KEKI, tvb(offset, 4)):append_text(" (Reserved for manually indexed keys)")
|
||||
end
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Cipher
|
||||
local cipher_node = ext_type_msg_tree:add(fields.cipher, tvb(offset, 1))
|
||||
local cipher = tvb(offset, 1):uint()
|
||||
if cipher == 0 then
|
||||
elseif cipher == 1 then
|
||||
cipher_node:append_text(" (AES-ECB(potentially for VF 2.0 compatible message))")
|
||||
elseif cipher == 2 then
|
||||
cipher_node:append_text(" (AES-CTR[FP800-38A])")
|
||||
else
|
||||
cipher_node:append_text(" (AES-CCM or AES-GCM)")
|
||||
end
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle Auth
|
||||
if tvb(offset, 1):uint() == 0 then
|
||||
ext_type_msg_tree:add(fields.auth, tvb(offset, 1)):append_text(" (None or KEKI indexed crypto context)")
|
||||
else
|
||||
ext_type_msg_tree:add(fields.auth, tvb(offset, 1))
|
||||
end
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle SE
|
||||
local SE_node = ext_type_msg_tree:add(fields.SE, tvb(offset, 1))
|
||||
local SE = tvb(offset, 1):uint()
|
||||
if SE == 0 then
|
||||
SE_node:append_text( " (Unspecified or KEKI indexed crypto context)")
|
||||
elseif SE == 1 then
|
||||
SE_node:append_text( " (MPEG-TS/UDP)")
|
||||
elseif SE == 2 then
|
||||
SE_node:append_text( " (MPEG-TS/SRT)")
|
||||
end
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle resv1
|
||||
ext_type_msg_tree:add(fields.resv1, tvb(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle resv2
|
||||
ext_type_msg_tree:add(fields.resv2, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle slen
|
||||
ext_type_msg_tree:add(fields.slen, tvb(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle klen
|
||||
local klen = tvb(offset, 1):uint()
|
||||
ext_type_msg_tree:add(fields.klen, tvb(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
-- Handle salt key
|
||||
ext_type_msg_tree:add(fields.salt, tvb(offset, slen * 4))
|
||||
offset = offset + slen * 4
|
||||
|
||||
-- Handle wrap
|
||||
-- Handle ICV
|
||||
local wrap_len = 8 + KK * klen
|
||||
local wrap_tree = ext_type_msg_tree:add(fields.wrap, tvb(offset, wrap_len))
|
||||
wrap_tree:add(fields.ICV, tvb(offset, 8))
|
||||
offset = offset + 8
|
||||
-- If KK == 2, first key is Even key
|
||||
if KK == 2 then
|
||||
wrap_tree:add(fields.even_key, tvb(offset, klen))
|
||||
offset = offset + klen;
|
||||
end
|
||||
|
||||
-- Handle Odd key
|
||||
wrap_tree:add(fields.odd_key, tvb(offset, klen))
|
||||
offset = offset + klen;
|
||||
elseif ext_type >= 5 and ext_type <= 8 then
|
||||
local value_size = tvb(offset + 2, 2):uint() * 4
|
||||
local ext_msg_size = 2 + 2 + value_size
|
||||
local type_array = { " [SRT_CMD_SID]", " [SRT_CMD_CONGESTION]", " [SRT_CMD_FILTER]", " [SRT_CMD_GROUP]" }
|
||||
local field_array = { fields.sid, fields.congestion, fields.filter, fields.group }
|
||||
local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, ext_msg_size)):append_text(type_array[ext_type - 4])
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Ext Msg Value Size
|
||||
ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2)):append_text(" (byte/4)")
|
||||
offset = offset + 2
|
||||
|
||||
-- Value
|
||||
local value_table = {}
|
||||
for pos = 0, value_size - 4, 4 do
|
||||
table.insert(value_table, string.char(tvb(offset + pos + 3, 1):uint()))
|
||||
table.insert(value_table, string.char(tvb(offset + pos + 2, 1):uint()))
|
||||
table.insert(value_table, string.char(tvb(offset + pos + 1, 1):uint()))
|
||||
table.insert(value_table, string.char(tvb(offset + pos, 1):uint()))
|
||||
end
|
||||
local value = table.concat(value_table)
|
||||
ext_type_msg_tree:add(field_array[ext_type - 4], tvb(offset, value_size), value)
|
||||
offset = offset + value_size
|
||||
elseif ext_type == -1 then
|
||||
local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, tvb:len() - offset)):append_text(" [SRT_CMD_NONE]")
|
||||
ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- none
|
||||
if offset == tvb:len() then
|
||||
return
|
||||
end
|
||||
ext_type_msg_tree:add(fields.none, tvb(offset, tvb:len() - offset))
|
||||
offset = tvb:len()
|
||||
end
|
||||
if offset == tvb:len() then
|
||||
return
|
||||
else
|
||||
process_ext_type()
|
||||
end
|
||||
end
|
||||
|
||||
process_ext_type()
|
||||
end,
|
||||
[1] = function()
|
||||
pinfo.cols.info:append(" [KEEPALIVE]")
|
||||
pack_type_tree:append_text(" [KEEPALIVE]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [KEEPALIVE]")
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Additional Info, Time Stamp and Destination Socket
|
||||
parse_three_param()
|
||||
end,
|
||||
[2] = function()
|
||||
pinfo.cols.info:append(" [ACK]")
|
||||
pack_type_tree:append_text(" [ACK]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle ACK Number
|
||||
subtree:add(fields.ack_num, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Time Stamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Destination Socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Last Ack Packet Sequence
|
||||
local last_ack_pack = tvb(offset, 4):uint()
|
||||
pinfo.cols.info:append(" (Last ACK Seq:" .. last_ack_pack .. ")")
|
||||
subtree:add(fields.last_ack_pack, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle RTT
|
||||
local rtt = tvb(offset, 4):int()
|
||||
subtree:add(fields.rtt, tvb(offset, 4)):append_text(" μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle RTT variance
|
||||
if rtt < 0 then
|
||||
subtree:add(fields.rtt_variance, tvb(offset, 4), -tvb(offset, 4):int())
|
||||
else
|
||||
subtree:add(fields.rtt_variance, tvb(offset, 4))
|
||||
end
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Available Buffer Size(pkts)
|
||||
subtree:add(fields.buf_size, tvb(offset, 4)):append_text(" pkts")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Packets Receiving Rate(Pkts/sec)
|
||||
subtree:add(fields.pack_rcv_rate, tvb(offset, 4)):append_text(" pkts/sec")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Estmated Link Capacity
|
||||
subtree:add(fields.est_link_capacity, tvb(offset, 4)):append_text(" pkts/sec")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Receiving Rate(bps)
|
||||
subtree:add(fields.rcv_rate, tvb(offset, 4)):append_text(" bps")
|
||||
offset = offset + 4
|
||||
end,
|
||||
[3] = function()
|
||||
pinfo.cols.info:append(" [NAK(loss Report)]")
|
||||
pack_type_tree:append_text(" [NAK(loss Report)]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Additional Info, Timestamp and Destination Socket
|
||||
parse_three_param()
|
||||
|
||||
-- Handle lost packet sequence
|
||||
-- lua does not support changing loop variables within loops, but in the form of closures
|
||||
-- https://blog.csdn.net/Ai102iA/article/details/75371239
|
||||
local start = offset
|
||||
local ending = tvb:len()
|
||||
local lost_list_tree = subtree:add(fields.lost_list_tree, tvb(offset, ending - offset))
|
||||
for start in function()
|
||||
local first_bit = bit.rshift(tvb(start, 1):uint(), 7)
|
||||
if first_bit == 1 then
|
||||
local lost_pack_range_tree = lost_list_tree:add(fields.lost_pack_range_tree, tvb(start, 8))
|
||||
local lost_start = bit.band(tvb(start, 4):uint(), 0x7FFFFFFF)
|
||||
lost_pack_range_tree:append_text(" (" .. lost_start .. " -> " .. tvb(start + 4, 4):uint() .. ")")
|
||||
lost_pack_range_tree:add(fields.lost_start, tvb(start, 4), lost_start)
|
||||
start = start + 4
|
||||
lost_pack_range_tree:add(fields.lost_up_to, tvb(start, 4))
|
||||
start = start + 4
|
||||
else
|
||||
lost_list_tree:add(fields.lost_pack_seq, tvb(start, 4))
|
||||
start = start + 4
|
||||
end
|
||||
return start
|
||||
end
|
||||
do
|
||||
if start == ending then
|
||||
break
|
||||
end
|
||||
end
|
||||
end,
|
||||
[4] = function()
|
||||
pinfo.cols.info:append(" [Congestion Warning]")
|
||||
pack_type_tree:append_text(" [Congestion Warning]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
end,
|
||||
[5] = function()
|
||||
pinfo.cols.info:append(" [Shutdown]")
|
||||
pack_type_tree:append_text(" [Shutdown]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Additional Info, Timestamp and Destination Socket
|
||||
parse_three_param()
|
||||
end,
|
||||
[6] = function()
|
||||
pinfo.cols.info:append(" [ACKACK]")
|
||||
pack_type_tree:append_text(" [ACKACK]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2))
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle ACK sequence number
|
||||
subtree:add(fields.ack_num, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Time Stamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Destination Socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Control Information
|
||||
subtree:add(fields.ctl_info, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
end,
|
||||
[7] = function()
|
||||
pinfo.cols.info:append(" [Drop Request]")
|
||||
pack_type_tree:append_text(" [Drop Request]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Drop Request]")
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
end,
|
||||
[8] = function()
|
||||
pinfo.cols.info:append(" [Peer Error]")
|
||||
pack_type_tree:append_text(" [Peer Error]")
|
||||
pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Peer Error]")
|
||||
pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
|
||||
offset = offset + 4
|
||||
end
|
||||
}
|
||||
-- Handle based on msg_type
|
||||
local case = switch[msg_type]
|
||||
if case then
|
||||
case()
|
||||
else
|
||||
-- default case
|
||||
subtree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Unknown Message Type]")
|
||||
offset = offset + 4
|
||||
end
|
||||
else
|
||||
-- If type field is '0x7FFF', it means an extended type, Handle Reserve field
|
||||
offset = offset + 2
|
||||
local msg_ext_type = tvb(offset, 2):uint()
|
||||
if msg_ext_type == 0 then
|
||||
pinfo.cols.info:append(" [Message Extension]")
|
||||
|
||||
pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Message Extension]")
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Additional Info, Time Stamp and Destination Socket
|
||||
parse_three_param()
|
||||
|
||||
-- Control information: defined by user
|
||||
elseif msg_ext_type == 1 or ext_type == 2 then
|
||||
if msg_ext_type == 1 then
|
||||
pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [SRT Handshake Request]")
|
||||
pinfo.cols.info:append(" [SRT Handshake Request]")
|
||||
elseif msg_ext_type == 2 then
|
||||
pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [SRT Handshake Response]")
|
||||
pinfo.cols.info:append(" [SRT Handshake Response]")
|
||||
end
|
||||
offset = offset + 2
|
||||
|
||||
-- Ignore additional info (this field is not defined in this packet type)
|
||||
subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Time Stamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text("μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Destination Socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle SRT Version field
|
||||
subtree:add(fields.srt_version, tvb(offset, 4))
|
||||
offset = ofssset + 4
|
||||
|
||||
-- Handle SRT Flags
|
||||
local SRT_flags_tree = subtree:add(fields.srt_flags, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tsbpdsnd, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tsbpdrcv, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_haicrypt, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_tlpktdrop, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_nakreport, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_rexmitflg, tvb(offset, 4))
|
||||
SRT_flags_tree:add(fields.srt_opt_stream, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle TsbPd Resv
|
||||
subtree:add(fields.tsbpb_resv, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle TsbPb Delay
|
||||
subtree:add(fields.tsbpb_delay, tvb(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- Handle Reserved field
|
||||
subtree:add(fields.reserve, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
elseif msg_ext_type == 3 or msg_ext_type == 4 then
|
||||
if msg_ext_type == 3 then
|
||||
pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Encryption Keying Material Request]")
|
||||
pinfo.cols.info:append(" [Encryption Keying Material Request]")
|
||||
elseif msg_ext_type == 4 then
|
||||
pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Encryption Keying Material Response]")
|
||||
pinfo.cols.info:append(" [Encryption Keying Material Response]")
|
||||
end
|
||||
offset = offset + 2
|
||||
|
||||
-- Ignore additional info (this field is not defined in this packet type)
|
||||
subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Timestamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text("μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Destination Socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle KmErr
|
||||
if msg_ext_type == 4 then
|
||||
subtree:add(fields.km_err, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
return
|
||||
end
|
||||
|
||||
-- The encrypted message is not handled
|
||||
end
|
||||
end
|
||||
else
|
||||
-- 0 -> Data Packet
|
||||
pack_type_tree:add(fields.pack_type, tvb(offset, 2))
|
||||
pack_type_tree:append_text(" (Data Packet)")
|
||||
local seq_num = tvb(offset, 4):uint()
|
||||
pinfo.cols.info:append(" (Data Packet)(Seq Num:" .. seq_num .. ")")
|
||||
|
||||
-- The first 4 bytes are the package sequence number
|
||||
subtree:add(fields.seq_num, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
data_flag_info_tree = subtree:add(fields.data_flag_info_tree, tvb(offset, 1))
|
||||
-- Handle FF flag
|
||||
local FF_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0xC0), 6)
|
||||
if FF_state == 0 then
|
||||
data_flag_info_tree:append_text(" [Middle packet]")
|
||||
elseif FF_state == 1 then
|
||||
data_flag_info_tree:append_text(" [Last packet]")
|
||||
elseif FF_state == 2 then
|
||||
data_flag_info_tree:append_text(" [First packet]")
|
||||
else
|
||||
data_flag_info_tree:append_text(" [Single packet]")
|
||||
end
|
||||
data_flag_info_tree:add(fields.FF_state, tvb(offset, 1))
|
||||
|
||||
-- Handle O flag
|
||||
local O_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x20), 5)
|
||||
if O_state == 0 then
|
||||
data_flag_info_tree:append_text(" [Data delivered unordered]")
|
||||
else
|
||||
data_flag_info_tree:append_text(" [Data delivered in order]")
|
||||
end
|
||||
data_flag_info_tree:add(fields.O_state, tvb(offset, 1))
|
||||
|
||||
-- Handle KK flag
|
||||
local KK_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x18), 3)
|
||||
if KK_state == 1 then
|
||||
data_flag_info_tree:append_text(" [Encrypted with even key]")
|
||||
elseif KK_state == 2 then
|
||||
data_flag_info_tree:append_text(" [Encrypted with odd key]")
|
||||
end
|
||||
data_flag_info_tree:add(fields.KK_state, tvb(offset, 1))
|
||||
|
||||
-- Handle R flag
|
||||
local R_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x04), 2)
|
||||
if R_state == 1 then
|
||||
data_flag_info_tree:append_text(" [Retransmit packet]")
|
||||
pinfo.cols.info:append(" [Retransmit packet]")
|
||||
end
|
||||
data_flag_info_tree:add(fields.R_state, tvb(offset, 1))
|
||||
|
||||
-- Handle message number
|
||||
local msg_num = tvb(offset, 4):uint()
|
||||
msg_num = bit.band(tvb(offset, 4):uint(), 0x03FFFFFF)
|
||||
-- subtree:add(fields.msg_num, bit.band(tvb(offset, 4):uint(), 0x03FFFFFF))
|
||||
subtree:add(fields.msg_num, tvb(offset, 4), msg_num)
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle Timestamp
|
||||
subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
|
||||
offset = offset + 4
|
||||
|
||||
-- Handle destination socket
|
||||
subtree:add(fields.dst_sock, tvb(offset, 4))
|
||||
offset = offset + 4
|
||||
end
|
||||
end
|
||||
|
||||
-- Add the protocol into udp table
|
||||
local port = 1935
|
||||
|
||||
local function enable_dissector()
|
||||
DissectorTable.get("udp.port"):add(port, srt_dev)
|
||||
end
|
||||
|
||||
-- Call it now - enabled by default
|
||||
enable_dissector()
|
||||
|
||||
local function disable_dissector()
|
||||
DissectorTable.get("udp.port"):remove(port, srt_dev)
|
||||
end
|
||||
|
||||
-- Prefs changed will listen at new port
|
||||
function srt_dev.prefs_changed()
|
||||
if port ~= srt_dev.prefs.srt_udp_port then
|
||||
if port ~= 0 then
|
||||
disable_dissector()
|
||||
end
|
||||
|
||||
port = srt_dev.prefs.srt_udp_port
|
||||
|
||||
if port ~= 0 then
|
||||
enable_dissector()
|
||||
end
|
||||
end
|
||||
end
|
|
@ -41,7 +41,7 @@ proc ReadBack {fd} {
|
|||
|
||||
# Nothing more to read
|
||||
if {$remain == 0} {
|
||||
puts stderr "NOTHING MORE TO BE WRITTEN - exitting"
|
||||
puts stderr "NOTHING MORE TO BE WRITTEN - exiting"
|
||||
set ::theend 1
|
||||
return
|
||||
}
|
||||
|
|
10
trunk/3rdparty/srt-1-fit/scripts/test_vista.c
vendored
Normal file
10
trunk/3rdparty/srt-1-fit/scripts/test_vista.c
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* Copyright © 2023 Steve Lhomme */
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#include <windows.h>
|
||||
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 /* _WIN32_WINNT_VISTA */
|
||||
#error NOPE
|
||||
#endif
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
10
trunk/3rdparty/srt-1-fit/scripts/win-installer/.gitignore
vendored
Normal file
10
trunk/3rdparty/srt-1-fit/scripts/win-installer/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
tmp
|
||||
installers
|
||||
*.exe
|
||||
*~
|
||||
~*
|
||||
.#*
|
||||
*.bak
|
||||
*.autosave
|
||||
.DS_Store
|
||||
._*
|
123
trunk/3rdparty/srt-1-fit/scripts/win-installer/README.md
vendored
Normal file
123
trunk/3rdparty/srt-1-fit/scripts/win-installer/README.md
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
# SRT Static Libraries Installer for Windows
|
||||
|
||||
This directory contains scripts to build a binary installer for
|
||||
libsrt on Windows systems for Visual Studio applications using SRT.
|
||||
|
||||
## SRT developer: Building the libsrt installer
|
||||
|
||||
### Prerequisites
|
||||
|
||||
These first two steps need to be executed once only.
|
||||
|
||||
- Prerequisite 1: Install OpenSSL for Windows, both 64 and 32 bits.
|
||||
This can be done automatically by running the PowerShell script `install-openssl.ps1`.
|
||||
|
||||
- Prerequisite 2: Install NSIS, the NullSoft Installation Scripting system.
|
||||
This can be done automatically by running the PowerShell script `install-nsis.ps1`.
|
||||
|
||||
### Building the libsrt installer
|
||||
|
||||
To build the libsrt installer, simply run the PowerShell script `build-win-installer.ps1`.
|
||||
Running it without parameters, for instance launching it from the Windows Explorer, is
|
||||
sufficient to build the installer.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
- `-Version name` :
|
||||
Use the specified string as version number for libsrt. By default, if the
|
||||
current commit has a tag, use that tag (initial "v" removed, for instance
|
||||
`1.4.3`). Otherwise, the defaut version is a detailed version number (most
|
||||
recent version, number of commits since then, short commit SHA, for instance
|
||||
`1.4.3-32-g22cc924`). Use that option if necessary to specify some other
|
||||
non-standard form of version string.
|
||||
|
||||
- `-NoPause` :
|
||||
Do not wait for the user to press `<enter>` at end of execution. By default,
|
||||
execute a `pause` instruction at the end of execution, which is useful
|
||||
when the script was launched from Windows Explorer. Use that option when the
|
||||
script is invoked from another PowerShell script.
|
||||
|
||||
The installer is then available in the directory `installers`.
|
||||
|
||||
The name of the installer is `libsrt-VERS.exe` where `VERS` is the SRT version number
|
||||
(see the `-Version` option).
|
||||
|
||||
The installer shall then be published as a release asset in the `srt` repository
|
||||
on GitHub, either as `libsrt-VERS.exe` or `libsrt-VERS-win-installer.zip`.
|
||||
In the latter case, the archive shall contain `libsrt-VERS.exe`.
|
||||
|
||||
## SRT user: Using the libsrt installer
|
||||
|
||||
### Installing the SRT libraries
|
||||
|
||||
To install the SRT libraries, simply run the `libsrt-VERS.exe` installer which is
|
||||
available in the [SRT release area](https://github.com/Haivision/srt/releases).
|
||||
|
||||
After installing the libsrt binaries, an environment variable named `LIBSRT` is
|
||||
defined with the installation root (typically `C:\Program Files (x86)\libsrt`).
|
||||
|
||||
If there is a need for automation, in a CI/CD pipeline for instance, the download
|
||||
of the latest `libsrt-VERS.exe` and its installation can be automated using the
|
||||
sample PowerShell script `install-libsrt.ps1` which is available in this directory.
|
||||
This script may be freely copied in the user's build environment.
|
||||
|
||||
When run without parameters (for instance from the Windows explorer), this
|
||||
script downloads and installs the latest version of libsrt.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
- `-Destination path` :
|
||||
Specify a local directory where the libsrt package will be downloaded.
|
||||
By default, use the `tmp` subdirectory from this script's directory.
|
||||
|
||||
- `-ForceDownload` :
|
||||
Force a download even if the package is already downloaded in the
|
||||
destination path. Note that the latest version is always checked.
|
||||
If a older package is already present but a newer one is available
|
||||
online, the newer one is always downloaded, even without this option.
|
||||
|
||||
- `-GitHubActions` :
|
||||
When used in a GitHub Actions workflow, make sure that the `LIBSRT`
|
||||
environment variable is propagated to subsequent jobs. In your GitHub
|
||||
workflow, in the initial setup phase, use
|
||||
`script-dir\install-libsrt.ps1 -GitHubActions -NoPause`.
|
||||
|
||||
- `-NoInstall` :
|
||||
Do not install the package, only download it. By default, libsrt is installed.
|
||||
|
||||
- `-NoPause` :
|
||||
Do not wait for the user to press `<enter>` at end of execution. By default,
|
||||
execute a `pause` instruction at the end of execution, which is useful
|
||||
when the script was launched from Windows Explorer. Use that option when the
|
||||
script is invoked from another PowerShell script.
|
||||
|
||||
### Building Windows applications with libsrt
|
||||
|
||||
In the SRT installation root directory (specified in environment variable `LIBSRT`),
|
||||
there is a Visual Studio property file named `libsrt.props`. Simply reference this
|
||||
property file in your Visual Studio project to use libsrt.
|
||||
|
||||
You can also do that manually by editing the application project file (the XML
|
||||
file named with a `.vcxproj` extension). Add the following line just before
|
||||
the end of the file:
|
||||
|
||||
~~~
|
||||
<Import Project="$(LIBSRT)\libsrt.props"/>
|
||||
~~~
|
||||
|
||||
With this setup, just compile your application normally, either using the
|
||||
Visual Studio IDE or the MSBuild command line tool.
|
||||
|
||||
## Files reference
|
||||
|
||||
This directory contains the following files:
|
||||
|
||||
| File name | Usage
|
||||
| ----------------------- | -----
|
||||
| build-win-installer.ps1 | PowerShell script to build the libsrt installer.
|
||||
| install-libsrt.ps1 | Sample PowerShell script to automatically install libsrt (for user's projects).
|
||||
| install-openssl.ps1 | PowerShell script to install OpenSSL (prerequisite to build the installer).
|
||||
| install-nsis.ps1 | PowerShell script to install NSIS (prerequisite to build the installer).
|
||||
| libsrt.nsi | NSIS installation script (used to build the installer).
|
||||
| libsrt.props | Visual Studio property files to use libsrt (embedded in the installer).
|
||||
| README.md | This text file.
|
227
trunk/3rdparty/srt-1-fit/scripts/win-installer/build-win-installer.ps1
vendored
Normal file
227
trunk/3rdparty/srt-1-fit/scripts/win-installer/build-win-installer.ps1
vendored
Normal file
|
@ -0,0 +1,227 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# SRT - Secure, Reliable, Transport
|
||||
# Copyright (c) 2021, Thierry Lelegard
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Build the SRT static libraries installer for Windows.
|
||||
|
||||
.PARAMETER Version
|
||||
|
||||
Use the specified string as version number from libsrt. By default, if
|
||||
the current commit has a tag, use that tag (initial 'v' removed). Otherwise,
|
||||
the defaut version is a detailed version number (most recent version, number
|
||||
of commits since then, short commit SHA).
|
||||
|
||||
.PARAMETER NoPause
|
||||
|
||||
Do not wait for the user to press <enter> at end of execution. By default,
|
||||
execute a "pause" instruction at the end of execution, which is useful
|
||||
when the script was run from Windows Explorer.
|
||||
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Version = "",
|
||||
[switch]$NoPause = $false
|
||||
)
|
||||
Write-Output "Building the SRT static libraries installer for Windows"
|
||||
|
||||
# Directory containing this script:
|
||||
$ScriptDir = $PSScriptRoot
|
||||
|
||||
# The root of the srt repository is two levels up.
|
||||
$RepoDir = (Split-Path -Parent (Split-Path -Parent $ScriptDir))
|
||||
|
||||
# Output directory for final installers:
|
||||
$OutDir = "$ScriptDir\installers"
|
||||
|
||||
# Temporary directory for build operations:
|
||||
$TmpDir = "$ScriptDir\tmp"
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# A function to exit this script with optional error message, using -NoPause
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
function Exit-Script([string]$Message = "")
|
||||
{
|
||||
$Code = 0
|
||||
if ($Message -ne "") {
|
||||
Write-Output "ERROR: $Message"
|
||||
$Code = 1
|
||||
}
|
||||
if (-not $NoPause) {
|
||||
pause
|
||||
}
|
||||
exit $Code
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Build SRT version strings
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# By default, let git format a decent version number.
|
||||
if (-not $Version) {
|
||||
$Version = (git describe --tags ) -replace '-g','-'
|
||||
}
|
||||
$Version = $Version -replace '^v',''
|
||||
|
||||
# Split version string in pieces and make sure to get at least four elements.
|
||||
$VField = ($Version -split "[-\. ]") + @("0", "0", "0", "0") | Select-String -Pattern '^\d*$'
|
||||
$VersionInfo = "$($VField[0]).$($VField[1]).$($VField[2]).$($VField[3])"
|
||||
|
||||
Write-Output "SRT version: $Version"
|
||||
Write-Output "Windows version info: $VersionInfo"
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Initialization phase, verify prerequisites
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Locate OpenSSL root from local installation.
|
||||
$SslRoot = @{
|
||||
"x64" = "C:\Program Files\OpenSSL-Win64";
|
||||
"Win32" = "C:\Program Files (x86)\OpenSSL-Win32"
|
||||
}
|
||||
|
||||
# Verify OpenSSL directories.
|
||||
$Missing = 0
|
||||
foreach ($file in @($SslRoot["x64"], $SslRoot["Win32"])) {
|
||||
if (-not (Test-Path $file)) {
|
||||
Write-Output "**** Missing $file"
|
||||
$Missing = $Missing + 1
|
||||
}
|
||||
}
|
||||
if ($Missing -gt 0) {
|
||||
Exit-Script "Missing $Missing OpenSSL files, use install-openssl.ps1 to install OpenSSL"
|
||||
}
|
||||
|
||||
# Locate MSBuild and CMake, regardless of Visual Studio version.
|
||||
Write-Output "Searching MSBuild ..."
|
||||
$MSRoots = @("C:\Program Files*\MSBuild", "C:\Program Files*\Microsoft Visual Studio", "C:\Program Files*\CMake*")
|
||||
$MSBuild = Get-ChildItem -Recurse -Path $MSRoots -Include MSBuild.exe -ErrorAction Ignore |
|
||||
ForEach-Object { (Get-Command $_).FileVersionInfo } |
|
||||
Sort-Object -Unique -Property FileVersion |
|
||||
ForEach-Object { $_.FileName} |
|
||||
Select-Object -Last 1
|
||||
if (-not $MSBuild) {
|
||||
Exit-Script "MSBuild not found"
|
||||
}
|
||||
|
||||
Write-Output "Searching CMake ..."
|
||||
$CMake = Get-ChildItem -Recurse -Path $MSRoots -Include cmake.exe -ErrorAction Ignore |
|
||||
ForEach-Object { (Get-Command $_).FileVersionInfo } |
|
||||
Sort-Object -Unique -Property FileVersion |
|
||||
ForEach-Object { $_.FileName} |
|
||||
Select-Object -Last 1
|
||||
if (-not $CMake) {
|
||||
Exit-Script "CMake not found, check option 'C++ CMake tools for Windows' in Visual Studio installer"
|
||||
}
|
||||
|
||||
# Locate NSIS, the Nullsoft Scriptable Installation System.
|
||||
Write-Output "Searching NSIS ..."
|
||||
$NSIS = Get-Item "C:\Program Files*\NSIS\makensis.exe" | ForEach-Object { $_.FullName} | Select-Object -Last 1
|
||||
if (-not $NSIS) {
|
||||
Exit-Script "NSIS not found, use install-nsis.ps1 to install NSIS"
|
||||
}
|
||||
|
||||
Write-Output "MSBuild: $MSBuild"
|
||||
Write-Output "CMake: $CMake"
|
||||
Write-Output "NSIS: $NSIS"
|
||||
|
||||
# Create the directories for builds when necessary.
|
||||
[void](New-Item -Path $TmpDir -ItemType Directory -Force)
|
||||
[void](New-Item -Path $OutDir -ItemType Directory -Force)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure and build SRT library using CMake on two architectures.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
foreach ($Platform in @("x64", "Win32")) {
|
||||
|
||||
# Build directory. Cleanup to force a fresh cmake config.
|
||||
$BuildDir = "$TmpDir\build.$Platform"
|
||||
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $BuildDir
|
||||
[void](New-Item -Path $BuildDir -ItemType Directory -Force)
|
||||
|
||||
# Run CMake.
|
||||
Write-Output "Configuring build for platform $Platform ..."
|
||||
$SRoot = $SslRoot[$Platform]
|
||||
& $CMake -S $RepoDir -B $BuildDir -A $Platform `
|
||||
-DENABLE_STDCXX_SYNC=ON `
|
||||
-DOPENSSL_ROOT_DIR="$SRoot" `
|
||||
-DOPENSSL_LIBRARIES="$SRoot\lib\libssl_static.lib;$SRoot\lib\libcrypto_static.lib" `
|
||||
-DOPENSSL_INCLUDE_DIR="$SRoot\include"
|
||||
|
||||
# Patch version string in version.h
|
||||
Get-Content "$BuildDir\version.h" |
|
||||
ForEach-Object {
|
||||
$_ -replace "#define *SRT_VERSION_STRING .*","#define SRT_VERSION_STRING `"$Version`""
|
||||
} |
|
||||
Out-File "$BuildDir\version.new" -Encoding ascii
|
||||
Move-Item "$BuildDir\version.new" "$BuildDir\version.h" -Force
|
||||
|
||||
# Compile SRT.
|
||||
Write-Output "Building for platform $Platform ..."
|
||||
foreach ($Conf in @("Release", "Debug")) {
|
||||
& $MSBuild "$BuildDir\SRT.sln" /nologo /maxcpucount /property:Configuration=$Conf /property:Platform=$Platform /target:srt_static
|
||||
}
|
||||
}
|
||||
|
||||
# Verify the presence of compiled libraries.
|
||||
Write-Output "Checking compiled libraries ..."
|
||||
$Missing = 0
|
||||
foreach ($Conf in @("Release", "Debug")) {
|
||||
foreach ($Platform in @("x64", "Win32")) {
|
||||
$Path = "$TmpDir\build.$Platform\$Conf\srt_static.lib"
|
||||
if (-not (Test-Path $Path)) {
|
||||
Write-Output "**** Missing $Path"
|
||||
$Missing = $Missing + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Missing -gt 0) {
|
||||
Exit-Script "Missing $Missing files"
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Build the binary installer.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
$InstallExe = "$OutDir\libsrt-$Version.exe"
|
||||
$InstallZip = "$OutDir\libsrt-$Version-win-installer.zip"
|
||||
|
||||
Write-Output "Building installer ..."
|
||||
& $NSIS /V2 `
|
||||
/DVersion="$Version" `
|
||||
/DVersionInfo="$VersionInfo" `
|
||||
/DOutDir="$OutDir" `
|
||||
/DBuildRoot="$TmpDir" `
|
||||
/DRepoDir="$RepoDir" `
|
||||
"$ScriptDir\libsrt.nsi"
|
||||
|
||||
if (-not (Test-Path $InstallExe)) {
|
||||
Exit-Script "**** Missing $InstallExe"
|
||||
}
|
||||
|
||||
Write-Output "Building installer archive ..."
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue $InstallZip
|
||||
Compress-Archive -Path $InstallExe -DestinationPath $InstallZip -CompressionLevel Optimal
|
||||
|
||||
if (-not (Test-Path $InstallZip)) {
|
||||
Exit-Script "**** Missing $InstallZip"
|
||||
}
|
||||
|
||||
Exit-Script
|
131
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-libsrt.ps1
vendored
Normal file
131
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-libsrt.ps1
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
# SRT library download and install for Windows.
|
||||
# Copyright (c) 2021, Thierry Lelegard
|
||||
# All rights reserved.
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Download and install the libsrt library for Windows. This script is
|
||||
provided to automate the build of Windows applications using libsrt.
|
||||
|
||||
.PARAMETER Destination
|
||||
|
||||
Specify a local directory where the libsrt package will be downloaded.
|
||||
By default, use "tmp" subdirectory from this script.
|
||||
|
||||
.PARAMETER ForceDownload
|
||||
|
||||
Force a download even if the package is already downloaded.
|
||||
|
||||
.PARAMETER GitHubActions
|
||||
|
||||
When used in a GitHub Actions workflow, make sure that the LIBSRT
|
||||
environment variable is propagated to subsequent jobs.
|
||||
|
||||
.PARAMETER NoInstall
|
||||
|
||||
Do not install the package. By default, libsrt is installed.
|
||||
|
||||
.PARAMETER NoPause
|
||||
|
||||
Do not wait for the user to press <enter> at end of execution. By default,
|
||||
execute a "pause" instruction at the end of execution, which is useful
|
||||
when the script was run from Windows Explorer.
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param(
|
||||
[string]$Destination = "",
|
||||
[switch]$ForceDownload = $false,
|
||||
[switch]$GitHubActions = $false,
|
||||
[switch]$NoInstall = $false,
|
||||
[switch]$NoPause = $false
|
||||
)
|
||||
|
||||
Write-Output "libsrt download and installation procedure"
|
||||
|
||||
# Default directory for downloaded products.
|
||||
if (-not $Destination) {
|
||||
$Destination = "$PSScriptRoot\tmp"
|
||||
}
|
||||
|
||||
# A function to exit this script.
|
||||
function Exit-Script([string]$Message = "")
|
||||
{
|
||||
$Code = 0
|
||||
if ($Message -ne "") {
|
||||
Write-Output "ERROR: $Message"
|
||||
$Code = 1
|
||||
}
|
||||
if (-not $NoPause) {
|
||||
pause
|
||||
}
|
||||
exit $Code
|
||||
}
|
||||
|
||||
# Without this, Invoke-WebRequest is awfully slow.
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Get the URL of the latest libsrt installer.
|
||||
$URL = (Invoke-RestMethod "https://api.github.com/repos/Haivision/srt/releases?per_page=20" |
|
||||
ForEach-Object { $_.assets } |
|
||||
ForEach-Object { $_.browser_download_url } |
|
||||
Select-String @("/libsrt-.*\.exe$", "/libsrt-.*-win-installer\.zip$") |
|
||||
Select-Object -First 1)
|
||||
|
||||
if (-not $URL) {
|
||||
Exit-Script "Could not find a libsrt installer on GitHub"
|
||||
}
|
||||
if (-not ($URL -match "\.zip$") -and -not ($URL -match "\.exe$")) {
|
||||
Exit-Script "Unexpected URL, not .exe, not .zip: $URL"
|
||||
}
|
||||
|
||||
# Installer name and path.
|
||||
$InstName = (Split-Path -Leaf $URL)
|
||||
$InstPath = "$Destination\$InstName"
|
||||
|
||||
# Create the directory for downloaded products when necessary.
|
||||
[void](New-Item -Path $Destination -ItemType Directory -Force)
|
||||
|
||||
# Download installer
|
||||
if (-not $ForceDownload -and (Test-Path $InstPath)) {
|
||||
Write-Output "$InstName already downloaded, use -ForceDownload to download again"
|
||||
}
|
||||
else {
|
||||
Write-Output "Downloading $URL ..."
|
||||
Invoke-WebRequest $URL.ToString() -UseBasicParsing -UserAgent Download -OutFile $InstPath
|
||||
if (-not (Test-Path $InstPath)) {
|
||||
Exit-Script "$URL download failed"
|
||||
}
|
||||
}
|
||||
|
||||
# If installer is an archive, expect an exe with same name inside.
|
||||
if ($InstName -match "\.zip$") {
|
||||
|
||||
# Expected installer name in archive.
|
||||
$ZipName = $InstName
|
||||
$ZipPath = $InstPath
|
||||
$InstName = $ZipName -replace '-win-installer.zip','.exe'
|
||||
$InstPath = "$Destination\$InstName"
|
||||
|
||||
# Extract the installer.
|
||||
Remove-Item -Force $InstPath -ErrorAction SilentlyContinue
|
||||
Write-Output "Expanding $ZipName ..."
|
||||
Expand-Archive $ZipPath -DestinationPath $Destination
|
||||
if (-not (Test-Path $InstPath)) {
|
||||
Exit-Script "$InstName not found in $ZipName"
|
||||
}
|
||||
}
|
||||
|
||||
# Install libsrt
|
||||
if (-not $NoInstall) {
|
||||
Write-Output "Installing $InstName"
|
||||
Start-Process -FilePath $InstPath -ArgumentList @("/S") -Wait
|
||||
}
|
||||
|
||||
# Propagate LIBSRT in next jobs for GitHub Actions.
|
||||
if ($GitHubActions -and (-not -not $env:GITHUB_ENV) -and (Test-Path $env:GITHUB_ENV)) {
|
||||
$libsrt = [System.Environment]::GetEnvironmentVariable("LIBSRT","Machine")
|
||||
Write-Output "LIBSRT=$libsrt" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
}
|
||||
|
||||
Exit-Script
|
122
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-nsis.ps1
vendored
Normal file
122
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-nsis.ps1
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# SRT - Secure, Reliable, Transport
|
||||
# Copyright (c) 2021, Thierry Lelegard
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Download, expand and install NSIS, the NullSoft Installer Scripting.
|
||||
|
||||
.PARAMETER ForceDownload
|
||||
|
||||
Force a download even if NSIS is already downloaded.
|
||||
|
||||
.PARAMETER NoInstall
|
||||
|
||||
Do not install the NSIS package. By default, NSIS is installed.
|
||||
|
||||
.PARAMETER NoPause
|
||||
|
||||
Do not wait for the user to press <enter> at end of execution. By default,
|
||||
execute a "pause" instruction at the end of execution, which is useful
|
||||
when the script was run from Windows Explorer.
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param(
|
||||
[switch]$ForceDownload = $false,
|
||||
[switch]$NoInstall = $false,
|
||||
[switch]$NoPause = $false
|
||||
)
|
||||
|
||||
Write-Output "NSIS download and installation procedure"
|
||||
$NSISPage = "https://nsis.sourceforge.io/Download"
|
||||
$FallbackURL = "http://prdownloads.sourceforge.net/nsis/nsis-3.05-setup.exe?download"
|
||||
|
||||
# A function to exit this script.
|
||||
function Exit-Script([string]$Message = "")
|
||||
{
|
||||
$Code = 0
|
||||
if ($Message -ne "") {
|
||||
Write-Output "ERROR: $Message"
|
||||
$Code = 1
|
||||
}
|
||||
if (-not $NoPause) {
|
||||
pause
|
||||
}
|
||||
exit $Code
|
||||
}
|
||||
|
||||
# Local file names.
|
||||
$RootDir = $PSScriptRoot
|
||||
$TmpDir = "$RootDir\tmp"
|
||||
|
||||
# Create the directory for external products when necessary.
|
||||
[void] (New-Item -Path $TmpDir -ItemType Directory -Force)
|
||||
|
||||
# Without this, Invoke-WebRequest is awfully slow.
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Get the HTML page for NSIS downloads.
|
||||
$status = 0
|
||||
$message = ""
|
||||
$Ref = $null
|
||||
try {
|
||||
$response = Invoke-WebRequest -UseBasicParsing -UserAgent Download -Uri $NSISPage
|
||||
$status = [int] [Math]::Floor($response.StatusCode / 100)
|
||||
}
|
||||
catch {
|
||||
$message = $_.Exception.Message
|
||||
}
|
||||
|
||||
if ($status -ne 1 -and $status -ne 2) {
|
||||
# Error fetch NSIS download page.
|
||||
if ($message -eq "" -and (Test-Path variable:response)) {
|
||||
Write-Output "Status code $($response.StatusCode), $($response.StatusDescription)"
|
||||
}
|
||||
else {
|
||||
Write-Output "#### Error accessing ${NSISPage}: $message"
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Parse HTML page to locate the latest installer.
|
||||
$Ref = $response.Links.href | Where-Object { $_ -like "*/nsis-*-setup.exe?download" } | Select-Object -First 1
|
||||
}
|
||||
|
||||
if (-not $Ref) {
|
||||
# Could not find a reference to NSIS installer.
|
||||
$Url = [System.Uri]$FallbackURL
|
||||
}
|
||||
else {
|
||||
# Build the absolute URL's from base URL (the download page) and href links.
|
||||
$Url = New-Object -TypeName 'System.Uri' -ArgumentList ([System.Uri]$NSISPage, $Ref)
|
||||
}
|
||||
|
||||
$InstallerName = (Split-Path -Leaf $Url.LocalPath)
|
||||
$InstallerPath = "$TmpDir\$InstallerName"
|
||||
|
||||
# Download installer
|
||||
if (-not $ForceDownload -and (Test-Path $InstallerPath)) {
|
||||
Write-Output "$InstallerName already downloaded, use -ForceDownload to download again"
|
||||
}
|
||||
else {
|
||||
Write-Output "Downloading $Url ..."
|
||||
Invoke-WebRequest -UseBasicParsing -UserAgent Download -Uri $Url -OutFile $InstallerPath
|
||||
if (-not (Test-Path $InstallerPath)) {
|
||||
Exit-Script "$Url download failed"
|
||||
}
|
||||
}
|
||||
|
||||
# Install NSIS
|
||||
if (-not $NoInstall) {
|
||||
Write-Output "Installing $InstallerName"
|
||||
Start-Process -FilePath $InstallerPath -ArgumentList @("/S") -Wait
|
||||
}
|
||||
|
||||
Exit-Script
|
119
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-openssl.ps1
vendored
Normal file
119
trunk/3rdparty/srt-1-fit/scripts/win-installer/install-openssl.ps1
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# SRT - Secure, Reliable, Transport
|
||||
# Copyright (c) 2021, Thierry Lelegard
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Download, expand and install OpenSSL for Windows.
|
||||
|
||||
.PARAMETER ForceDownload
|
||||
|
||||
Force a download even if the OpenSSL installers are already downloaded.
|
||||
|
||||
.PARAMETER NoInstall
|
||||
|
||||
Do not install the OpenSSL packages. By default, OpenSSL is installed.
|
||||
|
||||
.PARAMETER NoPause
|
||||
|
||||
Do not wait for the user to press <enter> at end of execution. By default,
|
||||
execute a "pause" instruction at the end of execution, which is useful
|
||||
when the script was run from Windows Explorer.
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param(
|
||||
[switch]$ForceDownload = $false,
|
||||
[switch]$NoInstall = $false,
|
||||
[switch]$NoPause = $false
|
||||
)
|
||||
|
||||
Write-Output "OpenSSL download and installation procedure"
|
||||
$OpenSSLHomePage = "http://slproweb.com/products/Win32OpenSSL.html"
|
||||
|
||||
# A function to exit this script.
|
||||
function Exit-Script([string]$Message = "")
|
||||
{
|
||||
$Code = 0
|
||||
if ($Message -ne "") {
|
||||
Write-Output "ERROR: $Message"
|
||||
$Code = 1
|
||||
}
|
||||
if (-not $NoPause) {
|
||||
pause
|
||||
}
|
||||
exit $Code
|
||||
}
|
||||
|
||||
# Local file names.
|
||||
$RootDir = $PSScriptRoot
|
||||
$TmpDir = "$RootDir\tmp"
|
||||
|
||||
# Create the directory for external products when necessary.
|
||||
[void] (New-Item -Path $TmpDir -ItemType Directory -Force)
|
||||
|
||||
# Without this, Invoke-WebRequest is awfully slow.
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Get the HTML page for OpenSSL downloads.
|
||||
$status = 0
|
||||
$message = ""
|
||||
try {
|
||||
$response = Invoke-WebRequest -UseBasicParsing -UserAgent Download -Uri $OpenSSLHomePage
|
||||
$status = [int] [Math]::Floor($response.StatusCode / 100)
|
||||
}
|
||||
catch {
|
||||
$message = $_.Exception.Message
|
||||
}
|
||||
if ($status -ne 1 -and $status -ne 2) {
|
||||
if ($message -eq "" -and (Test-Path variable:response)) {
|
||||
Exit-Script "Status code $($response.StatusCode), $($response.StatusDescription)"
|
||||
}
|
||||
else {
|
||||
Exit-Script "#### Error accessing ${OpenSSLHomePage}: $message"
|
||||
}
|
||||
}
|
||||
|
||||
# Parse HTML page to locate the latest MSI files.
|
||||
$Ref32 = $response.Links.href | Where-Object { $_ -like "*/Win32OpenSSL-*.msi" } | Select-Object -First 1
|
||||
$Ref64 = $response.Links.href | Where-Object { $_ -like "*/Win64OpenSSL-*.msi" } | Select-Object -First 1
|
||||
|
||||
# Build the absolute URL's from base URL (the download page) and href links.
|
||||
$Url32 = New-Object -TypeName 'System.Uri' -ArgumentList ([System.Uri]$OpenSSLHomePage, $Ref32)
|
||||
$Url64 = New-Object -TypeName 'System.Uri' -ArgumentList ([System.Uri]$OpenSSLHomePage, $Ref64)
|
||||
|
||||
# Download and install one MSI package.
|
||||
function Download-Install([string]$Url)
|
||||
{
|
||||
$MsiName = (Split-Path -Leaf $Url.toString())
|
||||
$MsiPath = "$TmpDir\$MsiName"
|
||||
|
||||
if (-not $ForceDownload -and (Test-Path $MsiPath)) {
|
||||
Write-Output "$MsiName already downloaded, use -ForceDownload to download again"
|
||||
}
|
||||
else {
|
||||
Write-Output "Downloading $Url ..."
|
||||
Invoke-WebRequest -UseBasicParsing -UserAgent Download -Uri $Url -OutFile $MsiPath
|
||||
}
|
||||
|
||||
if (-not (Test-Path $MsiPath)) {
|
||||
Exit-Script "$Url download failed"
|
||||
}
|
||||
|
||||
if (-not $NoInstall) {
|
||||
Write-Output "Installing $MsiName"
|
||||
Start-Process msiexec.exe -ArgumentList @("/i", $MsiPath, "/qn", "/norestart") -Wait
|
||||
}
|
||||
}
|
||||
|
||||
# Download and install the two MSI packages.
|
||||
Download-Install $Url32
|
||||
Download-Install $Url64
|
||||
Exit-Script
|
219
trunk/3rdparty/srt-1-fit/scripts/win-installer/libsrt.nsi
vendored
Normal file
219
trunk/3rdparty/srt-1-fit/scripts/win-installer/libsrt.nsi
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; SRT - Secure, Reliable, Transport
|
||||
; Copyright (c) 2021, Thierry Lelegard
|
||||
;
|
||||
; 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/.
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
;
|
||||
; NSIS script to build the SRT binary installer for Windows.
|
||||
; Do not invoke NSIS directly, use PowerShell script build-win-installer.ps1
|
||||
; to ensure that all parameters are properly passed.
|
||||
;
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
Name "SRT"
|
||||
Caption "SRT Libraries Installer"
|
||||
|
||||
!verbose push
|
||||
!verbose 0
|
||||
!include "MUI2.nsh"
|
||||
!include "Sections.nsh"
|
||||
!include "TextFunc.nsh"
|
||||
!include "FileFunc.nsh"
|
||||
!include "WinMessages.nsh"
|
||||
!include "x64.nsh"
|
||||
!verbose pop
|
||||
|
||||
!define ProductName "libsrt"
|
||||
!define Build32Dir "${BuildRoot}\build.Win32"
|
||||
!define Build64Dir "${BuildRoot}\build.x64"
|
||||
!define SSL32Dir "C:\Program Files (x86)\OpenSSL-Win32"
|
||||
!define SSL64Dir "C:\Program Files\OpenSSL-Win64"
|
||||
|
||||
; Installer file information.
|
||||
VIProductVersion ${VersionInfo}
|
||||
VIAddVersionKey ProductName "${ProductName}"
|
||||
VIAddVersionKey ProductVersion "${Version}"
|
||||
VIAddVersionKey Comments "The SRT static libraries for Visual C++ on Windows"
|
||||
VIAddVersionKey CompanyName "Haivision"
|
||||
VIAddVersionKey LegalCopyright "Copyright (c) 2021 Haivision Systems Inc."
|
||||
VIAddVersionKey FileVersion "${VersionInfo}"
|
||||
VIAddVersionKey FileDescription "SRT Installer"
|
||||
|
||||
; Name of binary installer file.
|
||||
OutFile "${OutDir}\${ProductName}-${Version}.exe"
|
||||
|
||||
; Generate a Unicode installer (default is ANSI).
|
||||
Unicode true
|
||||
|
||||
; Registry key for environment variables
|
||||
!define EnvironmentKey '"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
|
||||
; Registry entry for product info and uninstallation info.
|
||||
!define ProductKey "Software\${ProductName}"
|
||||
!define UninstallKey "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ProductName}"
|
||||
|
||||
; Use XP manifest.
|
||||
XPStyle on
|
||||
|
||||
; Request administrator privileges for Windows Vista and higher.
|
||||
RequestExecutionLevel admin
|
||||
|
||||
; "Modern User Interface" (MUI) settings.
|
||||
!define MUI_ABORTWARNING
|
||||
|
||||
; Default installation folder.
|
||||
InstallDir "$PROGRAMFILES\${ProductName}"
|
||||
|
||||
; Get installation folder from registry if available from a previous installation.
|
||||
InstallDirRegKey HKLM "${ProductKey}" "InstallDir"
|
||||
|
||||
; Installer pages.
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
; Uninstaller pages.
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
; Languages.
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
; Installation initialization.
|
||||
function .onInit
|
||||
; In 64-bit installers, don't use registry redirection.
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${EndIf}
|
||||
functionEnd
|
||||
|
||||
; Uninstallation initialization.
|
||||
function un.onInit
|
||||
; In 64-bit installers, don't use registry redirection.
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${EndIf}
|
||||
functionEnd
|
||||
|
||||
; Installation section
|
||||
Section "Install"
|
||||
|
||||
; Work on "all users" context, not current user.
|
||||
SetShellVarContext all
|
||||
|
||||
; Delete obsolete files from previous versions.
|
||||
Delete "$INSTDIR\LICENSE.pthread.txt"
|
||||
Delete "$INSTDIR\include\srt\srt4udt.h"
|
||||
Delete "$INSTDIR\include\srt\udt.h"
|
||||
Delete "$INSTDIR\lib\Release-x64\pthread.lib"
|
||||
Delete "$INSTDIR\lib\Release-Win32\pthread.lib"
|
||||
Delete "$INSTDIR\lib\Debug-x64\srt.pdb"
|
||||
Delete "$INSTDIR\lib\Debug-x64\pthread.pdb"
|
||||
Delete "$INSTDIR\lib\Debug-x64\pthread.lib"
|
||||
Delete "$INSTDIR\lib\Debug-Win32\srt.pdb"
|
||||
Delete "$INSTDIR\lib\Debug-Win32\pthread.pdb"
|
||||
Delete "$INSTDIR\lib\Debug-Win32\pthread.lib"
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
File /oname=LICENSE.txt "${RepoDir}\LICENSE"
|
||||
File "libsrt.props"
|
||||
|
||||
; Header files.
|
||||
CreateDirectory "$INSTDIR\include\srt"
|
||||
SetOutPath "$INSTDIR\include\srt"
|
||||
File "${RepoDir}\srtcore\access_control.h"
|
||||
File "${RepoDir}\srtcore\logging_api.h"
|
||||
File "${RepoDir}\srtcore\platform_sys.h"
|
||||
File "${RepoDir}\srtcore\srt.h"
|
||||
File "${RepoDir}\srtcore\udt.h"
|
||||
File "${Build64Dir}\version.h"
|
||||
|
||||
CreateDirectory "$INSTDIR\include\win"
|
||||
SetOutPath "$INSTDIR\include\win"
|
||||
File "${RepoDir}\common\win\syslog_defs.h"
|
||||
|
||||
; Libraries.
|
||||
CreateDirectory "$INSTDIR\lib"
|
||||
|
||||
CreateDirectory "$INSTDIR\lib\Release-x64"
|
||||
SetOutPath "$INSTDIR\lib\Release-x64"
|
||||
File /oname=srt.lib "${Build64Dir}\Release\srt_static.lib"
|
||||
File /oname=libcrypto.lib "${SSL64Dir}\lib\VC\static\libcrypto64MD.lib"
|
||||
File /oname=libssl.lib "${SSL64Dir}\lib\VC\static\libssl64MD.lib"
|
||||
|
||||
CreateDirectory "$INSTDIR\lib\Debug-x64"
|
||||
SetOutPath "$INSTDIR\lib\Debug-x64"
|
||||
File /oname=srt.lib "${Build64Dir}\Debug\srt_static.lib"
|
||||
File /oname=libcrypto.lib "${SSL64Dir}\lib\VC\static\libcrypto64MDd.lib"
|
||||
File /oname=libssl.lib "${SSL64Dir}\lib\VC\static\libssl64MDd.lib"
|
||||
|
||||
CreateDirectory "$INSTDIR\lib\Release-Win32"
|
||||
SetOutPath "$INSTDIR\lib\Release-Win32"
|
||||
File /oname=srt.lib "${Build32Dir}\Release\srt_static.lib"
|
||||
File /oname=libcrypto.lib "${SSL32Dir}\lib\VC\static\libcrypto32MD.lib"
|
||||
File /oname=libssl.lib "${SSL32Dir}\lib\VC\static\libssl32MD.lib"
|
||||
|
||||
CreateDirectory "$INSTDIR\lib\Debug-Win32"
|
||||
SetOutPath "$INSTDIR\lib\Debug-Win32"
|
||||
File /oname=srt.lib "${Build32Dir}\Debug\srt_static.lib"
|
||||
File /oname=libcrypto.lib "${SSL32Dir}\lib\VC\static\libcrypto32MDd.lib"
|
||||
File /oname=libssl.lib "${SSL32Dir}\lib\VC\static\libssl32MDd.lib"
|
||||
|
||||
; Add an environment variable to installation root.
|
||||
WriteRegStr HKLM ${EnvironmentKey} "LIBSRT" "$INSTDIR"
|
||||
|
||||
; Store installation folder in registry.
|
||||
WriteRegStr HKLM "${ProductKey}" "InstallDir" $INSTDIR
|
||||
|
||||
; Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Declare uninstaller in "Add/Remove Software" control panel
|
||||
WriteRegStr HKLM "${UninstallKey}" "DisplayName" "${ProductName}"
|
||||
WriteRegStr HKLM "${UninstallKey}" "Publisher" "Haivision"
|
||||
WriteRegStr HKLM "${UninstallKey}" "URLInfoAbout" "https://github.com/Haivision/srt"
|
||||
WriteRegStr HKLM "${UninstallKey}" "DisplayVersion" "${Version}"
|
||||
WriteRegStr HKLM "${UninstallKey}" "DisplayIcon" "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "${UninstallKey}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Get estimated size of installed files
|
||||
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
||||
IntFmt $0 "0x%08X" $0
|
||||
WriteRegDWORD HKLM "${UninstallKey}" "EstimatedSize" "$0"
|
||||
|
||||
; Notify applications of environment modifications
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
SectionEnd
|
||||
|
||||
; Uninstallation section
|
||||
Section "Uninstall"
|
||||
|
||||
; Work on "all users" context, not current user.
|
||||
SetShellVarContext all
|
||||
|
||||
; Get installation folder from registry
|
||||
ReadRegStr $0 HKLM "${ProductKey}" "InstallDir"
|
||||
|
||||
; Delete product registry entries
|
||||
DeleteRegKey HKCU "${ProductKey}"
|
||||
DeleteRegKey HKLM "${ProductKey}"
|
||||
DeleteRegKey HKLM "${UninstallKey}"
|
||||
DeleteRegValue HKLM ${EnvironmentKey} "LIBSRT"
|
||||
|
||||
; Delete product files.
|
||||
RMDir /r "$0\include"
|
||||
RMDir /r "$0\lib"
|
||||
Delete "$0\libsrt.props"
|
||||
Delete "$0\LICENSE*"
|
||||
Delete "$0\Uninstall.exe"
|
||||
RMDir "$0"
|
||||
|
||||
; Notify applications of environment modifications
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
SectionEnd
|
38
trunk/3rdparty/srt-1-fit/scripts/win-installer/libsrt.props
vendored
Normal file
38
trunk/3rdparty/srt-1-fit/scripts/win-installer/libsrt.props
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- Visual Studio or MSBuild property file to use SRT static library -->
|
||||
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- Normalize platform name to x64 and Win32 (some projects use x86 or Win64) -->
|
||||
<Choose>
|
||||
<When Condition="'$(Platform)' == 'x86'">
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<SrtPlatform>Win32</SrtPlatform>
|
||||
</PropertyGroup>
|
||||
</When>
|
||||
<When Condition="'$(Platform)' == 'Win64'">
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<SrtPlatform>x64</SrtPlatform>
|
||||
</PropertyGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<SrtPlatform>$(Platform)</SrtPlatform>
|
||||
</PropertyGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
|
||||
<!-- Compilation and link options -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(LIBSRT)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>srt.lib;libssl.lib;libcrypto.lib;crypt32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(LIBSRT)\lib\$(Configuration)-$(SrtPlatform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
</Project>
|
360
trunk/3rdparty/srt-1-fit/srtcore/ATTIC/ccc.cpp
vendored
360
trunk/3rdparty/srt-1-fit/srtcore/ATTIC/ccc.cpp
vendored
|
@ -1,360 +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 - 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 02/21/2013
|
||||
modified by
|
||||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "core.h"
|
||||
#include "ccc.h"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
CCC::CCC():
|
||||
m_iSYNInterval(CUDT::m_iSYNInterval),
|
||||
m_dPktSndPeriod(1.0),
|
||||
m_dCWndSize(16.0),
|
||||
m_iBandwidth(),
|
||||
m_dMaxCWndSize(),
|
||||
m_iMSS(),
|
||||
m_iSndCurrSeqNo(),
|
||||
m_iRcvRate(),
|
||||
m_iRTT(),
|
||||
m_pcParam(NULL),
|
||||
m_iPSize(0),
|
||||
m_UDT(),
|
||||
m_iACKPeriod(0),
|
||||
m_iACKInterval(0),
|
||||
m_bUserDefinedRTO(false),
|
||||
m_iRTO(-1),
|
||||
m_PerfInfo()
|
||||
{
|
||||
}
|
||||
|
||||
CCC::~CCC()
|
||||
{
|
||||
delete [] m_pcParam;
|
||||
}
|
||||
|
||||
void CCC::setACKTimer(int msINT)
|
||||
{
|
||||
m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT;
|
||||
}
|
||||
|
||||
void CCC::setACKInterval(int pktINT)
|
||||
{
|
||||
m_iACKInterval = pktINT;
|
||||
}
|
||||
|
||||
void CCC::setRTO(int usRTO)
|
||||
{
|
||||
m_bUserDefinedRTO = true;
|
||||
m_iRTO = usRTO;
|
||||
}
|
||||
|
||||
void CCC::sendCustomMsg(CPacket& pkt) const
|
||||
{
|
||||
CUDT* u = CUDT::getUDTHandle(m_UDT);
|
||||
|
||||
if (NULL != u)
|
||||
{
|
||||
pkt.m_iID = u->m_PeerID;
|
||||
#ifdef SRT_ENABLE_CTRLTSTAMP
|
||||
pkt.m_iTimeStamp = int(CTimer::getTime() - u->m_StartTime);
|
||||
#endif
|
||||
u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
const CPerfMon* CCC::getPerfInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
CUDT* u = CUDT::getUDTHandle(m_UDT);
|
||||
if (NULL != u)
|
||||
u->sample(&m_PerfInfo, false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &m_PerfInfo;
|
||||
}
|
||||
|
||||
void CCC::setMSS(int mss)
|
||||
{
|
||||
m_iMSS = mss;
|
||||
}
|
||||
|
||||
void CCC::setBandwidth(int bw)
|
||||
{
|
||||
m_iBandwidth = bw;
|
||||
}
|
||||
|
||||
void CCC::setSndCurrSeqNo(int32_t seqno)
|
||||
{
|
||||
m_iSndCurrSeqNo = seqno;
|
||||
}
|
||||
|
||||
void CCC::setRcvRate(int rcvrate)
|
||||
{
|
||||
m_iRcvRate = rcvrate;
|
||||
}
|
||||
|
||||
void CCC::setMaxCWndSize(int cwnd)
|
||||
{
|
||||
m_dMaxCWndSize = cwnd;
|
||||
}
|
||||
|
||||
void CCC::setRTT(int rtt)
|
||||
{
|
||||
m_iRTT = rtt;
|
||||
}
|
||||
|
||||
void CCC::setUserParam(const char* param, int size)
|
||||
{
|
||||
delete [] m_pcParam;
|
||||
m_pcParam = new char[size];
|
||||
memcpy(m_pcParam, param, size);
|
||||
m_iPSize = size;
|
||||
}
|
||||
|
||||
//
|
||||
CUDTCC::CUDTCC():
|
||||
m_iRCInterval(),
|
||||
m_LastRCTime(),
|
||||
m_bSlowStart(),
|
||||
m_iLastAck(),
|
||||
m_bLoss(),
|
||||
m_iLastDecSeq(),
|
||||
m_dLastDecPeriod(),
|
||||
m_iNAKCount(),
|
||||
m_iDecRandom(),
|
||||
m_iAvgNAKNum(),
|
||||
m_iDecCount()
|
||||
{
|
||||
}
|
||||
|
||||
void CUDTCC::init()
|
||||
{
|
||||
m_iRCInterval = m_iSYNInterval;
|
||||
m_LastRCTime = CTimer::getTime();
|
||||
setACKTimer(m_iRCInterval);
|
||||
|
||||
m_bSlowStart = true;
|
||||
m_iLastAck = m_iSndCurrSeqNo;
|
||||
m_bLoss = false;
|
||||
m_iLastDecSeq = CSeqNo::decseq(m_iLastAck);
|
||||
m_dLastDecPeriod = 1;
|
||||
m_iAvgNAKNum = 0;
|
||||
m_iNAKCount = 0;
|
||||
m_iDecRandom = 1;
|
||||
|
||||
m_dCWndSize = 16;
|
||||
m_dPktSndPeriod = 1;
|
||||
}
|
||||
|
||||
void CUDTCC::onACK(int32_t ack)
|
||||
{
|
||||
int64_t B = 0;
|
||||
double inc = 0;
|
||||
// Note: 1/24/2012
|
||||
// The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01
|
||||
// because the original was too small and caused sending rate to stay at low level
|
||||
// for long time.
|
||||
const double min_inc = 0.01;
|
||||
|
||||
uint64_t currtime = CTimer::getTime();
|
||||
if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval)
|
||||
return;
|
||||
|
||||
m_LastRCTime = currtime;
|
||||
|
||||
#ifdef SRT_ENABLE_BSTATS
|
||||
//m_iRcvRate is bytes/sec
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack);
|
||||
m_iLastAck = ack;
|
||||
|
||||
if (m_dCWndSize > m_dMaxCWndSize)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
m_dPktSndPeriod = 1000000.0 / ((m_iRcvRate + m_iMSS - 1) / m_iMSS);
|
||||
else
|
||||
m_dPktSndPeriod = (m_iRTT + m_iRCInterval) / m_dCWndSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_dCWndSize = ((m_iRcvRate + m_iMSS -1) / m_iMSS) / 1000000.0 * (m_iRTT + m_iRCInterval) + 16;
|
||||
#else
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack);
|
||||
m_iLastAck = ack;
|
||||
|
||||
if (m_dCWndSize > m_dMaxCWndSize)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
else
|
||||
m_dPktSndPeriod = (m_iRTT + m_iRCInterval) / m_dCWndSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16;
|
||||
#endif
|
||||
|
||||
// During Slow Start, no rate increase
|
||||
if (m_bSlowStart)
|
||||
return;
|
||||
|
||||
if (m_bLoss)
|
||||
{
|
||||
m_bLoss = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//m_iBandwidth is pkts/sec
|
||||
B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod);
|
||||
if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B))
|
||||
B = m_iBandwidth / 9;
|
||||
if (B <= 0)
|
||||
inc = min_inc;
|
||||
else
|
||||
{
|
||||
// inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS)
|
||||
// Beta = 1.5 * 10^(-6)
|
||||
|
||||
inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS;
|
||||
|
||||
if (inc < min_inc)
|
||||
inc = min_inc;
|
||||
}
|
||||
|
||||
m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval);
|
||||
}
|
||||
|
||||
void CUDTCC::onLoss(const int32_t* losslist, int)
|
||||
{
|
||||
//Slow Start stopped, if it hasn't yet
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
{
|
||||
// Set the sending rate to the receiving rate.
|
||||
#ifdef SRT_ENABLE_BSTATS
|
||||
//Need average packet size here for better send period
|
||||
m_dPktSndPeriod = 1000000.0 / ((m_iRcvRate + m_iMSS - 1) / m_iMSS);
|
||||
#else
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// If no receiving rate is observed, we have to compute the sending
|
||||
// rate according to the current window size, and decrease it
|
||||
// using the method below.
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
|
||||
}
|
||||
|
||||
m_bLoss = true;
|
||||
|
||||
if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0)
|
||||
{
|
||||
m_dLastDecPeriod = m_dPktSndPeriod;
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
|
||||
|
||||
m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125);
|
||||
m_iNAKCount = 1;
|
||||
m_iDecCount = 1;
|
||||
|
||||
m_iLastDecSeq = m_iSndCurrSeqNo;
|
||||
|
||||
// remove global synchronization using randomization
|
||||
srand(m_iLastDecSeq);
|
||||
m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
|
||||
if (m_iDecRandom < 1)
|
||||
m_iDecRandom = 1;
|
||||
}
|
||||
else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom)))
|
||||
{
|
||||
// 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
|
||||
m_iLastDecSeq = m_iSndCurrSeqNo;
|
||||
}
|
||||
}
|
||||
|
||||
void CUDTCC::onTimeout()
|
||||
{
|
||||
if (m_bSlowStart)
|
||||
{
|
||||
m_bSlowStart = false;
|
||||
if (m_iRcvRate > 0)
|
||||
#ifdef SRT_ENABLE_BSTATS
|
||||
// Need average packet size here
|
||||
m_dPktSndPeriod = 1000000.0 / ((m_iRcvRate + m_iMSS - 1) / m_iMSS);
|
||||
#else
|
||||
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
|
||||
#endif
|
||||
else
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
m_dLastDecPeriod = m_dPktSndPeriod;
|
||||
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2);
|
||||
m_iLastDecSeq = m_iLastAck;
|
||||
*/
|
||||
}
|
||||
}
|
219
trunk/3rdparty/srt-1-fit/srtcore/ATTIC/ccc.h
vendored
219
trunk/3rdparty/srt-1-fit/srtcore/ATTIC/ccc.h
vendored
|
@ -1,219 +0,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 02/28/2012
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __UDT_CCC_H__
|
||||
#define __UDT_CCC_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
class UDT_API CCC
|
||||
{
|
||||
friend class CUDT;
|
||||
|
||||
public:
|
||||
CCC();
|
||||
virtual ~CCC();
|
||||
|
||||
private:
|
||||
CCC(const CCC&);
|
||||
CCC& operator=(const CCC&) {return *this;}
|
||||
|
||||
public:
|
||||
|
||||
/// Callback function to be called (only) at the start of a UDT connection.
|
||||
/// note that this is different from CCC(), which is always called.
|
||||
|
||||
virtual void init() {}
|
||||
|
||||
/// Callback function to be called when a UDT connection is closed.
|
||||
|
||||
virtual void close() {}
|
||||
|
||||
/// Callback function to be called when an ACK packet is received.
|
||||
/// @param [in] ackno the data sequence number acknowledged by this ACK.
|
||||
|
||||
virtual void onACK(int32_t) {}
|
||||
|
||||
/// Callback function to be called when a loss report is received.
|
||||
/// @param [in] losslist list of sequence number of packets, in the format describled in packet.cpp.
|
||||
/// @param [in] size length of the loss list.
|
||||
|
||||
virtual void onLoss(const int32_t*, int) {}
|
||||
|
||||
/// Callback function to be called when a timeout event occurs.
|
||||
|
||||
virtual void onTimeout() {}
|
||||
|
||||
/// Callback function to be called when a data is sent.
|
||||
/// @param [in] seqno the data sequence number.
|
||||
/// @param [in] size the payload size.
|
||||
|
||||
virtual void onPktSent(const CPacket*) {}
|
||||
|
||||
/// Callback function to be called when a data is received.
|
||||
/// @param [in] seqno the data sequence number.
|
||||
/// @param [in] size the payload size.
|
||||
|
||||
virtual void onPktReceived(const CPacket*) {}
|
||||
|
||||
/// Callback function to Process a user defined packet.
|
||||
/// @param [in] pkt the user defined packet.
|
||||
|
||||
virtual void processCustomMsg(const CPacket*) {}
|
||||
|
||||
protected:
|
||||
|
||||
/// Set periodical acknowldging and the ACK period.
|
||||
/// @param [in] msINT the period to send an ACK.
|
||||
|
||||
void setACKTimer(int msINT);
|
||||
|
||||
/// Set packet-based acknowldging and the number of packets to send an ACK.
|
||||
/// @param [in] pktINT the number of packets to send an ACK.
|
||||
|
||||
void setACKInterval(int pktINT);
|
||||
|
||||
/// Set RTO value.
|
||||
/// @param [in] msRTO RTO in macroseconds.
|
||||
|
||||
void setRTO(int usRTO);
|
||||
|
||||
/// Send a user defined control packet.
|
||||
/// @param [in] pkt user defined packet.
|
||||
|
||||
void sendCustomMsg(CPacket& pkt) const;
|
||||
|
||||
/// retrieve performance information.
|
||||
/// @return Pointer to a performance info structure.
|
||||
|
||||
const CPerfMon* getPerfInfo();
|
||||
|
||||
/// Set user defined parameters.
|
||||
/// @param [in] param the paramters in one buffer.
|
||||
/// @param [in] size the size of the buffer.
|
||||
|
||||
void setUserParam(const char* param, int size);
|
||||
|
||||
private:
|
||||
void setMSS(int mss);
|
||||
void setMaxCWndSize(int cwnd);
|
||||
void setBandwidth(int bw);
|
||||
void setSndCurrSeqNo(int32_t seqno);
|
||||
void setRcvRate(int rcvrate);
|
||||
void setRTT(int rtt);
|
||||
|
||||
protected:
|
||||
const int32_t& m_iSYNInterval; // UDT constant parameter, SYN
|
||||
|
||||
double m_dPktSndPeriod; // Packet sending period, in microseconds
|
||||
double m_dCWndSize; // Congestion window size, in packets
|
||||
|
||||
int m_iBandwidth; // estimated bandwidth, packets per second
|
||||
double m_dMaxCWndSize; // maximum cwnd size, in packets
|
||||
|
||||
int m_iMSS; // Maximum Packet Size, including all packet headers
|
||||
int32_t m_iSndCurrSeqNo; // current maximum seq no sent out
|
||||
int m_iRcvRate; // packet arrive rate at receiver side, packets per second
|
||||
int m_iRTT; // current estimated RTT, microsecond
|
||||
|
||||
char* m_pcParam; // user defined parameter
|
||||
int m_iPSize; // size of m_pcParam
|
||||
|
||||
private:
|
||||
UDTSOCKET m_UDT; // The UDT entity that this congestion control algorithm is bound to
|
||||
|
||||
int m_iACKPeriod; // Periodical timer to send an ACK, in milliseconds
|
||||
int m_iACKInterval; // How many packets to send one ACK, in packets
|
||||
|
||||
bool m_bUserDefinedRTO; // if the RTO value is defined by users
|
||||
int m_iRTO; // RTO value, microseconds
|
||||
|
||||
CPerfMon m_PerfInfo; // protocol statistics information
|
||||
};
|
||||
|
||||
class CCCVirtualFactory
|
||||
{
|
||||
public:
|
||||
virtual ~CCCVirtualFactory() {}
|
||||
|
||||
virtual CCC* create() = 0;
|
||||
virtual CCCVirtualFactory* clone() = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CCCFactory: public CCCVirtualFactory
|
||||
{
|
||||
public:
|
||||
virtual ~CCCFactory() {}
|
||||
|
||||
virtual CCC* create() {return new T;}
|
||||
virtual CCCVirtualFactory* clone() {return new CCCFactory<T>;}
|
||||
};
|
||||
|
||||
class CUDTCC: public CCC
|
||||
{
|
||||
public:
|
||||
CUDTCC();
|
||||
|
||||
public:
|
||||
virtual void init();
|
||||
virtual void onACK(int32_t);
|
||||
virtual void onLoss(const int32_t*, int);
|
||||
virtual void onTimeout();
|
||||
|
||||
private:
|
||||
int m_iRCInterval; // UDT Rate control interval
|
||||
uint64_t m_LastRCTime; // last rate increase time
|
||||
bool m_bSlowStart; // if in slow start phase
|
||||
int32_t m_iLastAck; // last ACKed seq no
|
||||
bool m_bLoss; // if loss happened since last rate increase
|
||||
int32_t m_iLastDecSeq; // max pkt seq no sent out when last decrease happened
|
||||
double m_dLastDecPeriod; // value of pktsndperiod when last decrease happened
|
||||
int m_iNAKCount; // NAK counter
|
||||
int m_iDecRandom; // random threshold on decrease by number of loss events
|
||||
int m_iAvgNAKNum; // average number of NAKs per congestion
|
||||
int m_iDecCount; // number of decreases in a congestion epoch
|
||||
};
|
||||
|
||||
#endif
|
79
trunk/3rdparty/srt-1-fit/srtcore/access_control.h
vendored
Normal file
79
trunk/3rdparty/srt-1-fit/srtcore/access_control.h
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* SRT - Secure, Reliable, Transport
|
||||
* Copyright (c) 2020 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_F_ACCESS_CONTROL_H
|
||||
#define INC_F_ACCESS_CONTROL_H
|
||||
|
||||
// A list of rejection codes that are SRT specific.
|
||||
|
||||
#define SRT_REJX_FALLBACK 1000 // A code used in case when the application wants to report some problem, but can't precisely specify it.
|
||||
#define SRT_REJX_KEY_NOTSUP 1001 // The key used in the StreamID keyed string is not supported by the service.
|
||||
#define SRT_REJX_FILEPATH 1002 // The resource type designates a file and the path is either wrong syntax or not found
|
||||
#define SRT_REJX_HOSTNOTFOUND 1003 // The `h` host specification was not recognized by the service
|
||||
|
||||
// The list of http codes adopted for SRT.
|
||||
// An example C++ header for HTTP codes can be found at:
|
||||
// https://github.com/j-ulrich/http-status-codes-cpp
|
||||
|
||||
// Some of the unused code can be revived in the future, if there
|
||||
// happens to be a good reason for it.
|
||||
|
||||
#define SRT_REJX_BAD_REQUEST 1400 // General syntax error in the SocketID specification (also a fallback code for undefined cases)
|
||||
#define SRT_REJX_UNAUTHORIZED 1401 // Authentication failed, provided that the user was correctly identified and access to the required resource would be granted
|
||||
#define SRT_REJX_OVERLOAD 1402 // The server is too heavily loaded, or you have exceeded credits for accessing the service and the resource.
|
||||
#define SRT_REJX_FORBIDDEN 1403 // Access denied to the resource by any kind of reason.
|
||||
#define SRT_REJX_NOTFOUND 1404 // Resource not found at this time.
|
||||
#define SRT_REJX_BAD_MODE 1405 // The mode specified in `m` key in StreamID is not supported for this request.
|
||||
#define SRT_REJX_UNACCEPTABLE 1406 // The requested parameters specified in SocketID cannot be satisfied for the requested resource. Also when m=publish and the data format is not acceptable.
|
||||
// CODE NOT IN USE 407: unused: proxy functionality not predicted
|
||||
// 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 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
|
||||
#define SRT_REJX_NOTSUP_MEDIA 1415 // The media type is not supported by the application. This is the `t` key that specifies the media type as stream, file and auth, possibly extended by the application.
|
||||
// CODE NOT IN USE 416: unused: no detailed specification defined
|
||||
// CODE NOT IN USE 417: unused: expectations not supported
|
||||
// CODE NOT IN USE 418: unused: sharks do not drink tea
|
||||
// CODE NOT IN USE 419: not defined in HTTP
|
||||
// CODE NOT IN USE 420: not defined in HTTP
|
||||
// CODE NOT IN USE 421: unused: misdirection not supported
|
||||
// CODE NOT IN USE 422: unused: aligned to general 400
|
||||
#define SRT_REJX_LOCKED 1423 // The resource being accessed is locked for any access.
|
||||
#define SRT_REJX_FAILED_DEPEND 1424 // The request failed because it specified a dependent session ID that has been disconnected.
|
||||
// CODE NOT IN USE 425: unused: replaying not supported
|
||||
// CODE NOT IN USE 426: unused: tempting, but it requires resend in connected
|
||||
// CODE NOT IN USE 427: not defined in HTTP
|
||||
// CODE NOT IN USE 428: unused: renders to 409
|
||||
// CODE NOT IN USE 429: unused: renders to 402
|
||||
// CODE NOT IN USE 451: unused: renders to 403
|
||||
#define SRT_REJX_ISE 1500 // Unexpected internal server error
|
||||
#define SRT_REJX_UNIMPLEMENTED 1501 // The request was recognized, but the current version doesn't support it.
|
||||
#define SRT_REJX_GW 1502 // The server acts as a gateway and the target endpoint rejected the connection.
|
||||
#define SRT_REJX_DOWN 1503 // The service has been temporarily taken over by a stub reporting this error. The real service can be down for maintenance or crashed.
|
||||
// CODE NOT IN USE 504: unused: timeout not supported
|
||||
#define SRT_REJX_VERSION 1505 // SRT version not supported. This might be either unsupported backward compatibility, or an upper value of a version.
|
||||
// CODE NOT IN USE 506: unused: negotiation and references not supported
|
||||
#define SRT_REJX_NOROOM 1507 // The data stream cannot be archived due to lacking storage space. This is in case when the request type was to send a file or the live stream to be archived.
|
||||
// CODE NOT IN USE 508: unused: no redirection supported
|
||||
// CODE NOT IN USE 509: not defined in HTTP
|
||||
// CODE NOT IN USE 510: unused: extensions not supported
|
||||
// CODE NOT IN USE 511: unused: intercepting proxies not supported
|
||||
|
||||
|
||||
|
||||
#endif
|
6444
trunk/3rdparty/srt-1-fit/srtcore/api.cpp
vendored
6444
trunk/3rdparty/srt-1-fit/srtcore/api.cpp
vendored
File diff suppressed because it is too large
Load diff
614
trunk/3rdparty/srt-1-fit/srtcore/api.h
vendored
614
trunk/3rdparty/srt-1-fit/srtcore/api.h
vendored
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -45,14 +45,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/*****************************************************************************
|
||||
written by
|
||||
Yunhong Gu, last updated 09/28/2010
|
||||
Yunhong Gu, last updated 09/28/2010
|
||||
modified by
|
||||
Haivision Systems Inc.
|
||||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_API_H__
|
||||
#define __UDT_API_H__
|
||||
|
||||
#ifndef INC_SRT_API_H
|
||||
#define INC_SRT_API_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
@ -64,237 +63,436 @@ modified by
|
|||
#include "cache.h"
|
||||
#include "epoll.h"
|
||||
#include "handshake.h"
|
||||
#include "core.h"
|
||||
#if ENABLE_BONDING
|
||||
#include "group.h"
|
||||
#endif
|
||||
|
||||
// Please refer to structure and locking information provided in the
|
||||
// docs/dev/low-level-info.md document.
|
||||
|
||||
namespace srt
|
||||
{
|
||||
|
||||
class CUDT;
|
||||
|
||||
/// @brief Class CUDTSocket is a control layer on top of the CUDT core functionality layer.
|
||||
/// CUDTSocket owns CUDT.
|
||||
class CUDTSocket
|
||||
{
|
||||
public:
|
||||
CUDTSocket();
|
||||
~CUDTSocket();
|
||||
CUDTSocket()
|
||||
: m_Status(SRTS_INIT)
|
||||
, m_SocketID(0)
|
||||
, m_ListenSocket(0)
|
||||
, m_PeerID(0)
|
||||
#if ENABLE_BONDING
|
||||
, m_GroupMemberData()
|
||||
, m_GroupOf()
|
||||
#endif
|
||||
, m_iISN(0)
|
||||
, m_UDT(this)
|
||||
, m_AcceptCond()
|
||||
, m_AcceptLock()
|
||||
, m_uiBackLog(0)
|
||||
, m_iMuxID(-1)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
SRT_SOCKSTATUS m_Status; //< current socket state
|
||||
CUDTSocket(const CUDTSocket& ancestor)
|
||||
: m_Status(SRTS_INIT)
|
||||
, m_SocketID(0)
|
||||
, m_ListenSocket(0)
|
||||
, m_PeerID(0)
|
||||
#if ENABLE_BONDING
|
||||
, m_GroupMemberData()
|
||||
, m_GroupOf()
|
||||
#endif
|
||||
, m_iISN(0)
|
||||
, m_UDT(this, ancestor.m_UDT)
|
||||
, m_AcceptCond()
|
||||
, m_AcceptLock()
|
||||
, m_uiBackLog(0)
|
||||
, m_iMuxID(-1)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
/// Time when the socket is closed.
|
||||
/// When the socket is closed, it is not removed immediately from the list
|
||||
/// of sockets in order to prevent other methods from accessing invalid address.
|
||||
/// A timer is started and the socket will be removed after approximately
|
||||
/// 1 second (see CUDTUnited::checkBrokenSockets()).
|
||||
uint64_t m_ClosureTimeStamp;
|
||||
~CUDTSocket();
|
||||
|
||||
int m_iIPversion; //< IP version
|
||||
sockaddr* m_pSelfAddr; //< pointer to the local address of the socket
|
||||
sockaddr* m_pPeerAddr; //< pointer to the peer address of the socket
|
||||
void construct();
|
||||
|
||||
SRTSOCKET m_SocketID; //< socket ID
|
||||
SRTSOCKET m_ListenSocket; //< ID of the listener socket; 0 means this is an independent socket
|
||||
SRT_ATTR_GUARDED_BY(m_ControlLock)
|
||||
sync::atomic<SRT_SOCKSTATUS> m_Status; //< current socket state
|
||||
|
||||
SRTSOCKET m_PeerID; //< peer socket ID
|
||||
int32_t m_iISN; //< initial sequence number, used to tell different connection from same IP:port
|
||||
/// Time when the socket is closed.
|
||||
/// When the socket is closed, it is not removed immediately from the list
|
||||
/// of sockets in order to prevent other methods from accessing invalid address.
|
||||
/// A timer is started and the socket will be removed after approximately
|
||||
/// 1 second (see CUDTUnited::checkBrokenSockets()).
|
||||
sync::steady_clock::time_point m_tsClosureTimeStamp;
|
||||
|
||||
CUDT* m_pUDT; //< pointer to the UDT entity
|
||||
sockaddr_any m_SelfAddr; //< local address of the socket
|
||||
sockaddr_any m_PeerAddr; //< peer address of the socket
|
||||
|
||||
std::set<SRTSOCKET>* m_pQueuedSockets; //< set of connections waiting for accept()
|
||||
std::set<SRTSOCKET>* m_pAcceptSockets; //< set of accept()ed connections
|
||||
SRTSOCKET m_SocketID; //< socket ID
|
||||
SRTSOCKET m_ListenSocket; //< ID of the listener socket; 0 means this is an independent socket
|
||||
|
||||
pthread_cond_t m_AcceptCond; //< used to block "accept" call
|
||||
pthread_mutex_t m_AcceptLock; //< mutex associated to m_AcceptCond
|
||||
SRTSOCKET m_PeerID; //< peer socket ID
|
||||
#if ENABLE_BONDING
|
||||
groups::SocketData* m_GroupMemberData; //< Pointer to group member data, or NULL if not a group member
|
||||
CUDTGroup* m_GroupOf; //< Group this socket is a member of, or NULL if it isn't
|
||||
#endif
|
||||
|
||||
unsigned int m_uiBackLog; //< maximum number of connections in queue
|
||||
|
||||
int m_iMuxID; //< multiplexer ID
|
||||
|
||||
pthread_mutex_t m_ControlLock; //< lock this socket exclusively for control APIs: bind/listen/connect
|
||||
|
||||
static int64_t getPeerSpec(SRTSOCKET id, int32_t isn)
|
||||
{
|
||||
return (id << 30) + isn;
|
||||
}
|
||||
int64_t getPeerSpec()
|
||||
{
|
||||
return getPeerSpec(m_PeerID, m_iISN);
|
||||
}
|
||||
int32_t m_iISN; //< initial sequence number, used to tell different connection from same IP:port
|
||||
|
||||
private:
|
||||
CUDTSocket(const CUDTSocket&);
|
||||
CUDTSocket& operator=(const CUDTSocket&);
|
||||
CUDT m_UDT; //< internal SRT socket logic
|
||||
|
||||
public:
|
||||
std::set<SRTSOCKET> m_QueuedSockets; //< set of connections waiting for accept()
|
||||
|
||||
sync::Condition m_AcceptCond; //< used to block "accept" call
|
||||
sync::Mutex m_AcceptLock; //< mutex associated to m_AcceptCond
|
||||
|
||||
unsigned int m_uiBackLog; //< maximum number of connections in queue
|
||||
|
||||
// XXX A refactoring might be needed here.
|
||||
|
||||
// There are no reasons found why the socket can't contain a list iterator to a
|
||||
// multiplexer INSTEAD of m_iMuxID. There's no danger in this solution because
|
||||
// the multiplexer is never deleted until there's at least one socket using it.
|
||||
//
|
||||
// The multiplexer may even physically be contained in the CUDTUnited object,
|
||||
// just track the multiple users of it (the listener and the accepted sockets).
|
||||
// When deleting, you simply "unsubscribe" yourself from the multiplexer, which
|
||||
// will unref it and remove the list element by the iterator kept by the
|
||||
// socket.
|
||||
int m_iMuxID; //< multiplexer ID
|
||||
|
||||
sync::Mutex m_ControlLock; //< lock this socket exclusively for control APIs: bind/listen/connect
|
||||
|
||||
CUDT& core() { return m_UDT; }
|
||||
const CUDT& core() const { return m_UDT; }
|
||||
|
||||
static int64_t getPeerSpec(SRTSOCKET id, int32_t isn) { return (int64_t(id) << 30) + isn; }
|
||||
int64_t getPeerSpec() { return getPeerSpec(m_PeerID, m_iISN); }
|
||||
|
||||
SRT_SOCKSTATUS getStatus();
|
||||
|
||||
/// This function shall be called always wherever
|
||||
/// you'd like to call cudtsocket->m_pUDT->close(),
|
||||
/// from within the GC thread only (that is, only when
|
||||
/// the socket should be no longer visible in the
|
||||
/// connection, including for sending remaining data).
|
||||
void breakSocket_LOCKED();
|
||||
|
||||
/// This makes the socket no longer capable of performing any transmission
|
||||
/// operation, but continues to be responsive in the connection in order
|
||||
/// 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.
|
||||
void setBrokenClosed();
|
||||
void removeFromGroup(bool broken);
|
||||
|
||||
// Instrumentally used by select() and also required for non-blocking
|
||||
// mode check in groups
|
||||
bool readReady();
|
||||
bool writeReady() const;
|
||||
bool broken() const;
|
||||
|
||||
private:
|
||||
CUDTSocket& operator=(const CUDTSocket&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CUDTUnited
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CRendezvousQueue;
|
||||
friend class CUDT;
|
||||
friend class CUDTGroup;
|
||||
friend class CRendezvousQueue;
|
||||
friend class CCryptoControl;
|
||||
|
||||
public:
|
||||
CUDTUnited();
|
||||
~CUDTUnited();
|
||||
CUDTUnited();
|
||||
~CUDTUnited();
|
||||
|
||||
// Public constants
|
||||
static const int32_t MAX_SOCKET_VAL = SRTGROUP_MASK - 1; // maximum value for a regular socket
|
||||
|
||||
public:
|
||||
|
||||
static std::string CONID(SRTSOCKET sock);
|
||||
|
||||
/// initialize the UDT library.
|
||||
/// @return 0 if success, otherwise -1 is returned.
|
||||
|
||||
int startup();
|
||||
|
||||
/// release the UDT library.
|
||||
/// @return 0 if success, otherwise -1 is returned.
|
||||
|
||||
int cleanup();
|
||||
|
||||
/// Create a new UDT socket.
|
||||
/// @param [in] af IP version, IPv4 (AF_INET) or IPv6 (AF_INET6).
|
||||
/// @param [in] type (ignored)
|
||||
/// @return The new UDT socket ID, or INVALID_SOCK.
|
||||
|
||||
SRTSOCKET newSocket(int af, int );
|
||||
|
||||
/// Create a new UDT connection.
|
||||
/// @param [in] listen the listening UDT socket;
|
||||
/// @param [in] peer peer address.
|
||||
/// @param [in,out] hs handshake information from peer side (in), negotiated value (out);
|
||||
/// @return If the new connection is successfully created: 1 success, 0 already exist, -1 error.
|
||||
|
||||
int newConnection(const SRTSOCKET listen, const sockaddr* peer, CHandShake* hs, const CPacket& hspkt,
|
||||
ref_t<SRT_REJECT_REASON> r_error);
|
||||
|
||||
int installAcceptHook(const SRTSOCKET lsn, srt_listen_callback_fn* hook, void* opaq);
|
||||
|
||||
/// look up the UDT entity according to its ID.
|
||||
/// @param [in] u the UDT socket ID.
|
||||
/// @return Pointer to the UDT entity.
|
||||
|
||||
CUDT* lookup(const SRTSOCKET u);
|
||||
|
||||
/// Check the status of the UDT socket.
|
||||
/// @param [in] u the UDT socket ID.
|
||||
/// @return UDT socket status, or NONEXIST if not found.
|
||||
|
||||
SRT_SOCKSTATUS getStatus(const SRTSOCKET u);
|
||||
|
||||
// socket APIs
|
||||
|
||||
int bind(const SRTSOCKET u, const sockaddr* name, int namelen);
|
||||
int bind(const SRTSOCKET u, UDPSOCKET udpsock);
|
||||
int listen(const SRTSOCKET u, int backlog);
|
||||
SRTSOCKET accept(const SRTSOCKET listen, sockaddr* addr, int* addrlen);
|
||||
int connect(const SRTSOCKET u, const sockaddr* name, int namelen, int32_t forced_isn);
|
||||
int close(const SRTSOCKET u);
|
||||
int getpeername(const SRTSOCKET u, sockaddr* name, int* namelen);
|
||||
int getsockname(const SRTSOCKET u, sockaddr* name, int* namelen);
|
||||
int select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout);
|
||||
int selectEx(const std::vector<SRTSOCKET>& fds, std::vector<SRTSOCKET>* readfds, std::vector<SRTSOCKET>* writefds, std::vector<SRTSOCKET>* exceptfds, int64_t msTimeOut);
|
||||
int epoll_create();
|
||||
int epoll_add_usock(const int eid, const SRTSOCKET u, const int* events = NULL);
|
||||
int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
int epoll_remove_usock(const int eid, const SRTSOCKET u);
|
||||
int epoll_remove_ssock(const int eid, const SYSSOCKET s);
|
||||
int epoll_update_usock(const int eid, const SRTSOCKET u, const int* events = NULL);
|
||||
int epoll_update_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
int epoll_wait(const int eid, std::set<SRTSOCKET>* readfds, std::set<SRTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* lwfds = NULL);
|
||||
int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
|
||||
int32_t epoll_set(const int eid, int32_t flags);
|
||||
int epoll_release(const int eid);
|
||||
|
||||
/// record the UDT exception.
|
||||
/// @param [in] e pointer to a UDT exception instance.
|
||||
|
||||
void setError(CUDTException* e);
|
||||
|
||||
/// look up the most recent UDT exception.
|
||||
/// @return pointer to a UDT exception instance.
|
||||
|
||||
CUDTException* getError();
|
||||
|
||||
private:
|
||||
// void init();
|
||||
|
||||
private:
|
||||
std::map<SRTSOCKET, CUDTSocket*> m_Sockets; // stores all the socket structures
|
||||
|
||||
pthread_mutex_t m_ControlLock; // used to synchronize UDT API
|
||||
|
||||
pthread_mutex_t m_IDLock; // used to synchronize ID generation
|
||||
SRTSOCKET m_SocketIDGenerator; // seed to generate a new unique socket ID
|
||||
|
||||
std::map<int64_t, std::set<SRTSOCKET> > m_PeerRec;// record sockets from peers to avoid repeated connection request, int64_t = (socker_id << 30) + isn
|
||||
|
||||
private:
|
||||
pthread_key_t m_TLSError; // thread local error record (last error)
|
||||
static void TLSDestroy(void* e) {if (NULL != e) delete (CUDTException*)e;}
|
||||
|
||||
private:
|
||||
CUDTSocket* locate(const SRTSOCKET u);
|
||||
CUDTSocket* locate(const sockaddr* peer, const SRTSOCKET id, int32_t isn);
|
||||
void updateMux(CUDTSocket* s, const sockaddr* addr = NULL, const UDPSOCKET* = NULL);
|
||||
void updateListenerMux(CUDTSocket* s, const CUDTSocket* ls);
|
||||
|
||||
private:
|
||||
std::map<int, CMultiplexer> m_mMultiplexer; // UDP multiplexer
|
||||
pthread_mutex_t m_MultiplexerLock;
|
||||
|
||||
private:
|
||||
CCache<CInfoBlock>* m_pCache; // UDT network information cache
|
||||
|
||||
private:
|
||||
volatile bool m_bClosing;
|
||||
pthread_mutex_t m_GCStopLock;
|
||||
pthread_cond_t m_GCStopCond;
|
||||
|
||||
pthread_mutex_t m_InitLock;
|
||||
int m_iInstanceCount; // number of startup() called by application
|
||||
bool m_bGCStatus; // if the GC thread is working (true)
|
||||
|
||||
pthread_t m_GCThread;
|
||||
static void* garbageCollect(void*);
|
||||
|
||||
std::map<SRTSOCKET, CUDTSocket*> m_ClosedSockets; // temporarily store closed sockets
|
||||
|
||||
void checkBrokenSockets();
|
||||
void removeSocket(const SRTSOCKET u);
|
||||
|
||||
CEPoll m_EPoll; // handling epoll data structures and events
|
||||
|
||||
private:
|
||||
CUDTUnited(const CUDTUnited&);
|
||||
CUDTUnited& operator=(const CUDTUnited&);
|
||||
};
|
||||
|
||||
// Debug support
|
||||
inline std::string SockaddrToString(const sockaddr* sadr)
|
||||
{
|
||||
void* addr =
|
||||
sadr->sa_family == AF_INET ?
|
||||
(void*)&((sockaddr_in*)sadr)->sin_addr
|
||||
: sadr->sa_family == AF_INET6 ?
|
||||
(void*)&((sockaddr_in6*)sadr)->sin6_addr
|
||||
: 0;
|
||||
// (cast to (void*) is required because otherwise the 2-3 arguments
|
||||
// of ?: operator would have different types, which isn't allowed in C++.
|
||||
if ( !addr )
|
||||
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(sadr, sizeof(*sadr), hostbuf, 1024, NULL, 0, flags))
|
||||
enum ErrorHandling
|
||||
{
|
||||
output << hostbuf;
|
||||
ERH_RETURN,
|
||||
ERH_THROW,
|
||||
ERH_ABORT
|
||||
};
|
||||
static std::string CONID(SRTSOCKET sock);
|
||||
|
||||
/// initialize the UDT library.
|
||||
/// @return 0 if success, otherwise -1 is returned.
|
||||
int startup();
|
||||
|
||||
/// release the UDT library.
|
||||
/// @return 0 if success, otherwise -1 is returned.
|
||||
int cleanup();
|
||||
|
||||
/// Create a new UDT socket.
|
||||
/// @param [out] pps Variable (optional) to which the new socket will be written, if succeeded
|
||||
/// @return The new UDT socket ID, or INVALID_SOCK.
|
||||
SRTSOCKET newSocket(CUDTSocket** pps = NULL);
|
||||
|
||||
/// Create (listener-side) a new socket associated with the incoming connection request.
|
||||
/// @param [in] listen the listening socket ID.
|
||||
/// @param [in] peer peer address.
|
||||
/// @param [in,out] hs handshake information from peer side (in), negotiated value (out);
|
||||
/// @param [out] w_error error code in case of failure.
|
||||
/// @param [out] w_acpu reference to the existing associated socket if already exists.
|
||||
/// @return 1: if the new connection was successfully created (accepted), @a w_acpu is NULL;
|
||||
/// 0: the connection already exists (reference to the corresponding socket is returned in @a w_acpu).
|
||||
/// -1: The connection processing failed due to memory alloation error, exceeding listener's backlog,
|
||||
/// any error propagated from CUDT::open and CUDT::acceptAndRespond.
|
||||
int newConnection(const SRTSOCKET listen,
|
||||
const sockaddr_any& peer,
|
||||
const CPacket& hspkt,
|
||||
CHandShake& w_hs,
|
||||
int& w_error,
|
||||
CUDT*& w_acpu);
|
||||
|
||||
int installAcceptHook(const SRTSOCKET lsn, srt_listen_callback_fn* hook, void* opaq);
|
||||
int installConnectHook(const SRTSOCKET lsn, srt_connect_callback_fn* hook, void* opaq);
|
||||
|
||||
/// Check the status of the UDT socket.
|
||||
/// @param [in] u the UDT socket ID.
|
||||
/// @return UDT socket status, or NONEXIST if not found.
|
||||
SRT_SOCKSTATUS getStatus(const SRTSOCKET u);
|
||||
|
||||
// socket APIs
|
||||
|
||||
int bind(CUDTSocket* u, const sockaddr_any& name);
|
||||
int bind(CUDTSocket* u, UDPSOCKET udpsock);
|
||||
int listen(const SRTSOCKET u, int backlog);
|
||||
SRTSOCKET accept(const SRTSOCKET listen, sockaddr* addr, int* addrlen);
|
||||
SRTSOCKET accept_bond(const SRTSOCKET listeners[], int lsize, int64_t msTimeOut);
|
||||
int connect(SRTSOCKET u, const sockaddr* srcname, const sockaddr* tarname, int tarlen);
|
||||
int connect(const SRTSOCKET u, const sockaddr* name, int namelen, int32_t forced_isn);
|
||||
int connectIn(CUDTSocket* s, const sockaddr_any& target, int32_t forced_isn);
|
||||
#if ENABLE_BONDING
|
||||
int groupConnect(CUDTGroup* g, SRT_SOCKGROUPCONFIG targets[], int arraysize);
|
||||
int singleMemberConnect(CUDTGroup* g, SRT_SOCKGROUPCONFIG* target);
|
||||
#endif
|
||||
int close(const SRTSOCKET u);
|
||||
int close(CUDTSocket* s);
|
||||
void getpeername(const SRTSOCKET u, sockaddr* name, int* namelen);
|
||||
void getsockname(const SRTSOCKET u, sockaddr* name, int* namelen);
|
||||
int select(UDT::UDSET* readfds, UDT::UDSET* writefds, UDT::UDSET* exceptfds, const timeval* timeout);
|
||||
int selectEx(const std::vector<SRTSOCKET>& fds,
|
||||
std::vector<SRTSOCKET>* readfds,
|
||||
std::vector<SRTSOCKET>* writefds,
|
||||
std::vector<SRTSOCKET>* exceptfds,
|
||||
int64_t msTimeOut);
|
||||
int epoll_create();
|
||||
int epoll_clear_usocks(int eid);
|
||||
int epoll_add_usock(const int eid, const SRTSOCKET u, const int* events = NULL);
|
||||
int epoll_add_usock_INTERNAL(const int eid, CUDTSocket* s, const int* events);
|
||||
int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
int epoll_remove_usock(const int eid, const SRTSOCKET u);
|
||||
template <class EntityType>
|
||||
int epoll_remove_entity(const int eid, EntityType* ent);
|
||||
int epoll_remove_socket_INTERNAL(const int eid, CUDTSocket* ent);
|
||||
#if ENABLE_BONDING
|
||||
int epoll_remove_group_INTERNAL(const int eid, CUDTGroup* ent);
|
||||
#endif
|
||||
int epoll_remove_ssock(const int eid, const SYSSOCKET s);
|
||||
int epoll_update_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
|
||||
int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
|
||||
int32_t epoll_set(const int eid, int32_t flags);
|
||||
int epoll_release(const int eid);
|
||||
|
||||
#if ENABLE_BONDING
|
||||
// [[using locked(m_GlobControlLock)]]
|
||||
CUDTGroup& addGroup(SRTSOCKET id, SRT_GROUP_TYPE type)
|
||||
{
|
||||
// This only ensures that the element exists.
|
||||
// If the element was newly added, it will be NULL.
|
||||
CUDTGroup*& g = m_Groups[id];
|
||||
if (!g)
|
||||
{
|
||||
// This is a reference to the cell, so it will
|
||||
// rewrite it into the map.
|
||||
g = new CUDTGroup(type);
|
||||
}
|
||||
|
||||
// Now we are sure that g is not NULL,
|
||||
// and persistence of this object is in the map.
|
||||
// The reference to the object can be safely returned here.
|
||||
return *g;
|
||||
}
|
||||
|
||||
output << ":" << ntohs(((sockaddr_in*)sadr)->sin_port); // TRICK: sin_port and sin6_port have the same offset and size
|
||||
return output.str();
|
||||
}
|
||||
void deleteGroup(CUDTGroup* g);
|
||||
void deleteGroup_LOCKED(CUDTGroup* g);
|
||||
|
||||
// [[using locked(m_GlobControlLock)]]
|
||||
CUDTGroup* findPeerGroup_LOCKED(SRTSOCKET peergroup)
|
||||
{
|
||||
for (groups_t::iterator i = m_Groups.begin(); i != m_Groups.end(); ++i)
|
||||
{
|
||||
if (i->second->peerid() == peergroup)
|
||||
return i->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
CEPoll& epoll_ref() { return m_EPoll; }
|
||||
|
||||
private:
|
||||
/// Generates a new socket ID. This function starts from a randomly
|
||||
/// generated value (at initialization time) and goes backward with
|
||||
/// with next calls. The possible values come from the range without
|
||||
/// the SRTGROUP_MASK bit, and the group bit is set when the ID is
|
||||
/// generated for groups. It is also internally checked if the
|
||||
/// newly generated ID isn't already used by an existing socket or group.
|
||||
///
|
||||
/// Socket ID value range.
|
||||
/// - [0]: reserved for handshake procedure. If the destination Socket ID is 0
|
||||
/// (destination Socket ID unknown) the packet will be sent to the listening socket
|
||||
/// or to a socket that is in the rendezvous connection phase.
|
||||
/// - [1; 2 ^ 30): single socket ID range.
|
||||
/// - (2 ^ 30; 2 ^ 31): group socket ID range. Effectively any positive number
|
||||
/// from [1; 2 ^ 30) with bit 30 set to 1. Bit 31 is zero.
|
||||
/// The most significant bit 31 (sign bit) is left unused so that checking for a value <= 0 identifies an invalid
|
||||
/// socket ID.
|
||||
///
|
||||
/// @param group The socket id should be for socket group.
|
||||
/// @return The new socket ID.
|
||||
/// @throw CUDTException if after rolling over all possible ID values nothing can be returned
|
||||
SRTSOCKET generateSocketID(bool group = false);
|
||||
|
||||
private:
|
||||
typedef std::map<SRTSOCKET, CUDTSocket*> sockets_t; // stores all the socket structures
|
||||
sockets_t m_Sockets;
|
||||
|
||||
#if ENABLE_BONDING
|
||||
typedef std::map<SRTSOCKET, CUDTGroup*> groups_t;
|
||||
groups_t m_Groups;
|
||||
#endif
|
||||
|
||||
sync::Mutex m_GlobControlLock; // used to synchronize UDT API
|
||||
|
||||
sync::Mutex m_IDLock; // used to synchronize ID generation
|
||||
|
||||
SRTSOCKET m_SocketIDGenerator; // seed to generate a new unique socket ID
|
||||
SRTSOCKET m_SocketIDGenerator_init; // Keeps track of the very first one
|
||||
|
||||
std::map<int64_t, std::set<SRTSOCKET> >
|
||||
m_PeerRec; // record sockets from peers to avoid repeated connection request, int64_t = (socker_id << 30) + isn
|
||||
|
||||
private:
|
||||
friend struct FLookupSocketWithEvent_LOCKED;
|
||||
|
||||
CUDTSocket* locateSocket(SRTSOCKET u, ErrorHandling erh = ERH_RETURN);
|
||||
// This function does the same as locateSocket, except that:
|
||||
// - lock on m_GlobControlLock is expected (so that you don't unlock between finding and using)
|
||||
// - only return NULL if not found
|
||||
CUDTSocket* locateSocket_LOCKED(SRTSOCKET u);
|
||||
CUDTSocket* locatePeer(const sockaddr_any& peer, const SRTSOCKET id, int32_t isn);
|
||||
|
||||
#if ENABLE_BONDING
|
||||
CUDTGroup* locateAcquireGroup(SRTSOCKET u, ErrorHandling erh = ERH_RETURN);
|
||||
CUDTGroup* acquireSocketsGroup(CUDTSocket* s);
|
||||
|
||||
struct GroupKeeper
|
||||
{
|
||||
CUDTGroup* group;
|
||||
|
||||
// This is intended for API functions to lock the group's existence
|
||||
// for the lifetime of their call.
|
||||
GroupKeeper(CUDTUnited& glob, SRTSOCKET id, ErrorHandling erh) { group = glob.locateAcquireGroup(id, erh); }
|
||||
|
||||
// This is intended for TSBPD thread that should lock the group's
|
||||
// existence until it exits.
|
||||
GroupKeeper(CUDTUnited& glob, CUDTSocket* s) { group = glob.acquireSocketsGroup(s); }
|
||||
|
||||
~GroupKeeper()
|
||||
{
|
||||
if (group)
|
||||
{
|
||||
// We have a guarantee that if `group` was set
|
||||
// as non-NULL here, it is also acquired and will not
|
||||
// be deleted until this busy flag is set back to false.
|
||||
sync::ScopedLock cgroup(*group->exp_groupLock());
|
||||
group->apiRelease();
|
||||
// Only now that the group lock is lifted, can the
|
||||
// group be now deleted and this pointer potentially dangling
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
void updateMux(CUDTSocket* s, const sockaddr_any& addr, const UDPSOCKET* = NULL);
|
||||
bool updateListenerMux(CUDTSocket* s, const CUDTSocket* ls);
|
||||
|
||||
// Utility functions for updateMux
|
||||
void configureMuxer(CMultiplexer& w_m, const CUDTSocket* s, int af);
|
||||
uint16_t installMuxer(CUDTSocket* w_s, CMultiplexer& sm);
|
||||
|
||||
/// @brief Checks if channel configuration matches the socket configuration.
|
||||
/// @param cfgMuxer multiplexer configuration.
|
||||
/// @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<int, CMultiplexer> m_mMultiplexer; // UDP multiplexer
|
||||
sync::Mutex m_MultiplexerLock;
|
||||
|
||||
private:
|
||||
CCache<CInfoBlock>* m_pCache; // UDT network information cache
|
||||
|
||||
private:
|
||||
srt::sync::atomic<bool> m_bClosing;
|
||||
sync::Mutex m_GCStopLock;
|
||||
sync::Condition m_GCStopCond;
|
||||
|
||||
sync::Mutex m_InitLock;
|
||||
int m_iInstanceCount; // number of startup() called by application
|
||||
bool m_bGCStatus; // if the GC thread is working (true)
|
||||
|
||||
sync::CThread m_GCThread;
|
||||
static void* garbageCollect(void*);
|
||||
|
||||
sockets_t m_ClosedSockets; // temporarily store closed sockets
|
||||
#if ENABLE_BONDING
|
||||
groups_t m_ClosedGroups;
|
||||
#endif
|
||||
|
||||
void checkBrokenSockets();
|
||||
void removeSocket(const SRTSOCKET u);
|
||||
|
||||
CEPoll m_EPoll; // handling epoll data structures and events
|
||||
|
||||
private:
|
||||
CUDTUnited(const CUDTUnited&);
|
||||
CUDTUnited& operator=(const CUDTUnited&);
|
||||
};
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif
|
||||
|
|
311
trunk/3rdparty/srt-1-fit/srtcore/atomic.h
vendored
Normal file
311
trunk/3rdparty/srt-1-fit/srtcore/atomic.h
vendored
Normal file
|
@ -0,0 +1,311 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
//
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
// this software, either in source code form or as a compiled binary, for any
|
||||
// purpose, commercial or non-commercial, and by any means.
|
||||
//
|
||||
// In jurisdictions that recognize copyright laws, the author or authors of
|
||||
// this software dedicate any and all copyright interest in the software to the
|
||||
// public domain. We make this dedication for the benefit of the public at
|
||||
// large and to the detriment of our heirs and successors. We intend this
|
||||
// dedication to be an overt act of relinquishment in perpetuity of all present
|
||||
// and future rights to this software under copyright law.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// For more information, please refer to <http://unlicense.org/>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// SRT Project information:
|
||||
// This file was adopted from a Public Domain project from
|
||||
// https://github.com/mbitsnbites/atomic
|
||||
// Only namespaces were changed to adopt it for SRT project.
|
||||
|
||||
#ifndef SRT_SYNC_ATOMIC_H_
|
||||
#define SRT_SYNC_ATOMIC_H_
|
||||
|
||||
// Macro for disallowing copying of an object.
|
||||
#if __cplusplus >= 201103L
|
||||
#define ATOMIC_DISALLOW_COPY(T) \
|
||||
T(const T&) = delete; \
|
||||
T& operator=(const T&) = delete;
|
||||
#else
|
||||
#define ATOMIC_DISALLOW_COPY(T) \
|
||||
T(const T&); \
|
||||
T& operator=(const T&);
|
||||
#endif
|
||||
|
||||
// A portable static assert.
|
||||
#if __cplusplus >= 201103L
|
||||
#define ATOMIC_STATIC_ASSERT(condition, message) \
|
||||
static_assert((condition), message)
|
||||
#else
|
||||
// Based on: http://stackoverflow.com/a/809465/5778708
|
||||
#define ATOMIC_STATIC_ASSERT(condition, message) \
|
||||
_impl_STATIC_ASSERT_LINE(condition, __LINE__)
|
||||
#define _impl_PASTE(a, b) a##b
|
||||
#ifdef __GNUC__
|
||||
#define _impl_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define _impl_UNUSED
|
||||
#endif
|
||||
#define _impl_STATIC_ASSERT_LINE(condition, line) \
|
||||
typedef char _impl_PASTE( \
|
||||
STATIC_ASSERT_failed_, \
|
||||
line)[(2 * static_cast<int>(!!(condition))) - 1] _impl_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
// NOTE: Defined at the top level.
|
||||
#elif __cplusplus >= 201103L
|
||||
// NOTE: Prefer to use the c++11 std::atomic.
|
||||
#define ATOMIC_USE_CPP11_ATOMIC
|
||||
#elif (defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5)) \
|
||||
|| defined(__xlc__)
|
||||
// NOTE: Clang <6 does not support GCC __atomic_* intrinsics. I am unsure
|
||||
// about Clang6. Since Clang sets __GNUC__ and __GNUC_MINOR__ of this era
|
||||
// to <4.5, older Clang will catch the setting below to use the
|
||||
// POSIX Mutex Implementation.
|
||||
#define ATOMIC_USE_GCC_INTRINSICS
|
||||
#elif defined(__GNUC__) \
|
||||
&& ( (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) )
|
||||
// NOTE: The __atomic_* family of intrisics were introduced in GCC-4.7.0.
|
||||
// NOTE: This follows #if defined(__clang__), because most if, not all,
|
||||
// versions of Clang define __GNUC__ and __GNUC_MINOR__ but often define
|
||||
// them to 4.4 or an even earlier version. Most of the newish versions
|
||||
// of Clang also support GCC Atomic Intrisics even if they set GCC version
|
||||
// macros to <4.7.
|
||||
#define ATOMIC_USE_GCC_INTRINSICS
|
||||
#elif defined(__GNUC__) && !defined(ATOMIC_USE_SRT_SYNC_MUTEX)
|
||||
// NOTE: GCC compiler built-ins for atomic operations are pure
|
||||
// compiler extensions prior to GCC-4.7 and were grouped into the
|
||||
// the __sync_* family of functions. GCC-4.7, both the c++11 and C11
|
||||
// standards had been finalized, and GCC updated their built-ins to
|
||||
// better reflect the new memory model and the new functions grouped
|
||||
// into the __atomic_* family. Also the memory models were defined
|
||||
// differently, than in pre 4.7.
|
||||
// TODO: PORT to the pre GCC-4.7 __sync_* intrinsics. In the meantime use
|
||||
// the POSIX Mutex Implementation.
|
||||
#define ATOMIC_USE_SRT_SYNC_MUTEX 1
|
||||
#elif defined(_MSC_VER)
|
||||
#define ATOMIC_USE_MSVC_INTRINSICS
|
||||
#include "atomic_msvc.h"
|
||||
#else
|
||||
#error Unsupported compiler / system.
|
||||
#endif
|
||||
// Include any necessary headers for the selected Atomic Implementation.
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
#include "sync.h"
|
||||
#endif
|
||||
#if defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
namespace srt {
|
||||
namespace sync {
|
||||
template <typename T>
|
||||
class atomic {
|
||||
public:
|
||||
ATOMIC_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||
|
||||
sizeof(T) == 8,
|
||||
"Only types of size 1, 2, 4 or 8 are supported");
|
||||
|
||||
atomic()
|
||||
: value_(static_cast<T>(0))
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
, mutex_()
|
||||
#endif
|
||||
{
|
||||
// No-Op
|
||||
}
|
||||
|
||||
explicit atomic(const T value)
|
||||
: value_(value)
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
, mutex_()
|
||||
#endif
|
||||
{
|
||||
// No-Op
|
||||
}
|
||||
|
||||
~atomic()
|
||||
{
|
||||
// No-Op
|
||||
}
|
||||
|
||||
/// @brief Performs an atomic increment operation (value + 1).
|
||||
/// @returns The new value of the atomic object.
|
||||
T operator++() {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
const T t = ++value_;
|
||||
return t;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
return __atomic_add_fetch(&value_, 1, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
return msvc::interlocked<T>::increment(&value_);
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
return ++value_;
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Performs an atomic decrement operation (value - 1).
|
||||
/// @returns The new value of the atomic object.
|
||||
T operator--() {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
const T t = --value_;
|
||||
return t;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
return __atomic_sub_fetch(&value_, 1, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
return msvc::interlocked<T>::decrement(&value_);
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
return --value_;
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Performs an atomic compare-and-swap (CAS) operation.
|
||||
///
|
||||
/// The value of the atomic object is only updated to the new value if the
|
||||
/// old value of the atomic object matches @c expected_val.
|
||||
///
|
||||
/// @param expected_val The expected value of the atomic object.
|
||||
/// @param new_val The new value to write to the atomic object.
|
||||
/// @returns True if new_value was written to the atomic object.
|
||||
bool compare_exchange(const T expected_val, const T new_val) {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
bool result = false;
|
||||
if (expected_val == value_)
|
||||
{
|
||||
value_ = new_val;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
T e = expected_val;
|
||||
return __atomic_compare_exchange_n(
|
||||
&value_, &e, new_val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
const T old_val =
|
||||
msvc::interlocked<T>::compare_exchange(&value_, new_val, expected_val);
|
||||
return (old_val == expected_val);
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
T e = expected_val;
|
||||
return value_.compare_exchange_weak(e, new_val);
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Performs an atomic set operation.
|
||||
///
|
||||
/// The value of the atomic object is unconditionally updated to the new
|
||||
/// value.
|
||||
///
|
||||
/// @param new_val The new value to write to the atomic object.
|
||||
void store(const T new_val) {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
value_ = new_val;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
__atomic_store_n(&value_, new_val, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
(void)msvc::interlocked<T>::exchange(&value_, new_val);
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
value_.store(new_val);
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @returns the current value of the atomic object.
|
||||
/// @note Be careful about how this is used, since any operations on the
|
||||
/// returned value are inherently non-atomic.
|
||||
T load() const {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
const T t = value_;
|
||||
return t;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
return __atomic_load_n(&value_, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
// TODO(m): Is there a better solution for MSVC?
|
||||
return value_;
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
return value_;
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Performs an atomic exchange operation.
|
||||
///
|
||||
/// The value of the atomic object is unconditionally updated to the new
|
||||
/// value, and the old value is returned.
|
||||
///
|
||||
/// @param new_val The new value to write to the atomic object.
|
||||
/// @returns the old value.
|
||||
T exchange(const T new_val) {
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
ScopedLock lg_(mutex_);
|
||||
const T t = value_;
|
||||
value_ = new_val;
|
||||
return t;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
return __atomic_exchange_n(&value_, new_val, __ATOMIC_SEQ_CST);
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
return msvc::interlocked<T>::exchange(&value_, new_val);
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
return value_.exchange(new_val);
|
||||
#else
|
||||
#error "Implement Me."
|
||||
#endif
|
||||
}
|
||||
|
||||
T operator=(const T new_value) {
|
||||
store(new_value);
|
||||
return new_value;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return load();
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
|
||||
T value_;
|
||||
mutable Mutex mutex_;
|
||||
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
|
||||
volatile T value_;
|
||||
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
|
||||
volatile T value_;
|
||||
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
|
||||
std::atomic<T> value_;
|
||||
#else
|
||||
#error "Implement Me. (value_ type)"
|
||||
#endif
|
||||
|
||||
ATOMIC_DISALLOW_COPY(atomic)
|
||||
};
|
||||
|
||||
} // namespace sync
|
||||
} // namespace srt
|
||||
|
||||
// Undef temporary defines.
|
||||
#undef ATOMIC_USE_GCC_INTRINSICS
|
||||
#undef ATOMIC_USE_MSVC_INTRINSICS
|
||||
#undef ATOMIC_USE_CPP11_ATOMIC
|
||||
|
||||
#endif // ATOMIC_ATOMIC_H_
|
91
trunk/3rdparty/srt-1-fit/srtcore/atomic_clock.h
vendored
Normal file
91
trunk/3rdparty/srt-1-fit/srtcore/atomic_clock.h
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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_SYNC_ATOMIC_CLOCK_H
|
||||
#define INC_SRT_SYNC_ATOMIC_CLOCK_H
|
||||
|
||||
#include "sync.h"
|
||||
#include "atomic.h"
|
||||
|
||||
namespace srt
|
||||
{
|
||||
namespace sync
|
||||
{
|
||||
|
||||
template <class Clock>
|
||||
class AtomicDuration
|
||||
{
|
||||
atomic<int64_t> dur;
|
||||
typedef typename Clock::duration duration_type;
|
||||
typedef typename Clock::time_point time_point_type;
|
||||
public:
|
||||
|
||||
AtomicDuration() ATR_NOEXCEPT : dur(0) {}
|
||||
|
||||
duration_type load()
|
||||
{
|
||||
int64_t val = dur.load();
|
||||
return duration_type(val);
|
||||
}
|
||||
|
||||
void store(const duration_type& d)
|
||||
{
|
||||
dur.store(d.count());
|
||||
}
|
||||
|
||||
AtomicDuration<Clock>& operator=(const duration_type& s)
|
||||
{
|
||||
dur = s.count();
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator duration_type() const
|
||||
{
|
||||
return duration_type(dur);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Clock>
|
||||
class AtomicClock
|
||||
{
|
||||
atomic<uint64_t> dur;
|
||||
typedef typename Clock::duration duration_type;
|
||||
typedef typename Clock::time_point time_point_type;
|
||||
public:
|
||||
|
||||
AtomicClock() ATR_NOEXCEPT : dur(0) {}
|
||||
|
||||
time_point_type load() const
|
||||
{
|
||||
int64_t val = dur.load();
|
||||
return time_point_type(duration_type(val));
|
||||
}
|
||||
|
||||
void store(const time_point_type& d)
|
||||
{
|
||||
dur.store(uint64_t(d.time_since_epoch().count()));
|
||||
}
|
||||
|
||||
AtomicClock& operator=(const time_point_type& s)
|
||||
{
|
||||
dur = s.time_since_epoch().count();
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator time_point_type() const
|
||||
{
|
||||
return time_point_type(duration_type(dur.load()));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sync
|
||||
} // namespace srt
|
||||
|
||||
#endif // INC_SRT_SYNC_ATOMIC_CLOCK_H
|
245
trunk/3rdparty/srt-1-fit/srtcore/atomic_msvc.h
vendored
Normal file
245
trunk/3rdparty/srt-1-fit/srtcore/atomic_msvc.h
vendored
Normal file
|
@ -0,0 +1,245 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
//
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
// this software, either in source code form or as a compiled binary, for any
|
||||
// purpose, commercial or non-commercial, and by any means.
|
||||
//
|
||||
// In jurisdictions that recognize copyright laws, the author or authors of
|
||||
// this software dedicate any and all copyright interest in the software to the
|
||||
// public domain. We make this dedication for the benefit of the public at
|
||||
// large and to the detriment of our heirs and successors. We intend this
|
||||
// dedication to be an overt act of relinquishment in perpetuity of all present
|
||||
// and future rights to this software under copyright law.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// For more information, please refer to <http://unlicense.org/>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// SRT Project information:
|
||||
// This file was adopted from a Public Domain project from
|
||||
// https://github.com/mbitsnbites/atomic
|
||||
// Only namespaces were changed to adopt it for SRT project.
|
||||
|
||||
#ifndef SRT_SYNC_ATOMIC_MSVC_H_
|
||||
#define SRT_SYNC_ATOMIC_MSVC_H_
|
||||
|
||||
// Define which functions we need (don't include <intrin.h>).
|
||||
extern "C" {
|
||||
short _InterlockedIncrement16(short volatile*);
|
||||
long _InterlockedIncrement(long volatile*);
|
||||
__int64 _InterlockedIncrement64(__int64 volatile*);
|
||||
|
||||
short _InterlockedDecrement16(short volatile*);
|
||||
long _InterlockedDecrement(long volatile*);
|
||||
__int64 _InterlockedDecrement64(__int64 volatile*);
|
||||
|
||||
char _InterlockedExchange8(char volatile*, char);
|
||||
short _InterlockedExchange16(short volatile*, short);
|
||||
long __cdecl _InterlockedExchange(long volatile*, long);
|
||||
__int64 _InterlockedExchange64(__int64 volatile*, __int64);
|
||||
|
||||
char _InterlockedCompareExchange8(char volatile*, char, char);
|
||||
short _InterlockedCompareExchange16(short volatile*, short, short);
|
||||
long __cdecl _InterlockedCompareExchange(long volatile*, long, long);
|
||||
__int64 _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
|
||||
};
|
||||
|
||||
// Define which functions we want to use as inline intriniscs.
|
||||
#pragma intrinsic(_InterlockedIncrement)
|
||||
#pragma intrinsic(_InterlockedIncrement16)
|
||||
|
||||
#pragma intrinsic(_InterlockedDecrement)
|
||||
#pragma intrinsic(_InterlockedDecrement16)
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
#pragma intrinsic(_InterlockedCompareExchange8)
|
||||
#pragma intrinsic(_InterlockedCompareExchange16)
|
||||
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
#pragma intrinsic(_InterlockedExchange8)
|
||||
#pragma intrinsic(_InterlockedExchange16)
|
||||
|
||||
#if defined(_M_X64)
|
||||
#pragma intrinsic(_InterlockedIncrement64)
|
||||
#pragma intrinsic(_InterlockedDecrement64)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
#pragma intrinsic(_InterlockedExchange64)
|
||||
#endif // _M_X64
|
||||
|
||||
namespace srt {
|
||||
namespace sync {
|
||||
namespace msvc {
|
||||
template <typename T, size_t N = sizeof(T)>
|
||||
struct interlocked {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct interlocked<T, 1> {
|
||||
static inline T increment(T volatile* x) {
|
||||
// There's no _InterlockedIncrement8().
|
||||
char old_val, new_val;
|
||||
do {
|
||||
old_val = static_cast<char>(*x);
|
||||
new_val = old_val + static_cast<char>(1);
|
||||
} while (_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(x),
|
||||
new_val,
|
||||
old_val) != old_val);
|
||||
return static_cast<T>(new_val);
|
||||
}
|
||||
|
||||
static inline T decrement(T volatile* x) {
|
||||
// There's no _InterlockedDecrement8().
|
||||
char old_val, new_val;
|
||||
do {
|
||||
old_val = static_cast<char>(*x);
|
||||
new_val = old_val - static_cast<char>(1);
|
||||
} while (_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(x),
|
||||
new_val,
|
||||
old_val) != old_val);
|
||||
return static_cast<T>(new_val);
|
||||
}
|
||||
|
||||
static inline T compare_exchange(T volatile* x,
|
||||
const T new_val,
|
||||
const T expected_val) {
|
||||
return static_cast<T>(
|
||||
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(x),
|
||||
static_cast<const char>(new_val),
|
||||
static_cast<const char>(expected_val)));
|
||||
}
|
||||
|
||||
static inline T exchange(T volatile* x, const T new_val) {
|
||||
return static_cast<T>(_InterlockedExchange8(
|
||||
reinterpret_cast<volatile char*>(x), static_cast<const char>(new_val)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct interlocked<T, 2> {
|
||||
static inline T increment(T volatile* x) {
|
||||
return static_cast<T>(
|
||||
_InterlockedIncrement16(reinterpret_cast<volatile short*>(x)));
|
||||
}
|
||||
|
||||
static inline T decrement(T volatile* x) {
|
||||
return static_cast<T>(
|
||||
_InterlockedDecrement16(reinterpret_cast<volatile short*>(x)));
|
||||
}
|
||||
|
||||
static inline T compare_exchange(T volatile* x,
|
||||
const T new_val,
|
||||
const T expected_val) {
|
||||
return static_cast<T>(
|
||||
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(x),
|
||||
static_cast<const short>(new_val),
|
||||
static_cast<const short>(expected_val)));
|
||||
}
|
||||
|
||||
static inline T exchange(T volatile* x, const T new_val) {
|
||||
return static_cast<T>(
|
||||
_InterlockedExchange16(reinterpret_cast<volatile short*>(x),
|
||||
static_cast<const short>(new_val)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct interlocked<T, 4> {
|
||||
static inline T increment(T volatile* x) {
|
||||
return static_cast<T>(
|
||||
_InterlockedIncrement(reinterpret_cast<volatile long*>(x)));
|
||||
}
|
||||
|
||||
static inline T decrement(T volatile* x) {
|
||||
return static_cast<T>(
|
||||
_InterlockedDecrement(reinterpret_cast<volatile long*>(x)));
|
||||
}
|
||||
|
||||
static inline T compare_exchange(T volatile* x,
|
||||
const T new_val,
|
||||
const T expected_val) {
|
||||
return static_cast<T>(
|
||||
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(x),
|
||||
static_cast<const long>(new_val),
|
||||
static_cast<const long>(expected_val)));
|
||||
}
|
||||
|
||||
static inline T exchange(T volatile* x, const T new_val) {
|
||||
return static_cast<T>(_InterlockedExchange(
|
||||
reinterpret_cast<volatile long*>(x), static_cast<const long>(new_val)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct interlocked<T, 8> {
|
||||
static inline T increment(T volatile* x) {
|
||||
#if defined(_M_X64)
|
||||
return static_cast<T>(
|
||||
_InterlockedIncrement64(reinterpret_cast<volatile __int64*>(x)));
|
||||
#else
|
||||
// There's no _InterlockedIncrement64() for 32-bit x86.
|
||||
__int64 old_val, new_val;
|
||||
do {
|
||||
old_val = static_cast<__int64>(*x);
|
||||
new_val = old_val + static_cast<__int64>(1);
|
||||
} while (_InterlockedCompareExchange64(
|
||||
reinterpret_cast<volatile __int64*>(x), new_val, old_val) !=
|
||||
old_val);
|
||||
return static_cast<T>(new_val);
|
||||
#endif // _M_X64
|
||||
}
|
||||
|
||||
static inline T decrement(T volatile* x) {
|
||||
#if defined(_M_X64)
|
||||
return static_cast<T>(
|
||||
_InterlockedDecrement64(reinterpret_cast<volatile __int64*>(x)));
|
||||
#else
|
||||
// There's no _InterlockedDecrement64() for 32-bit x86.
|
||||
__int64 old_val, new_val;
|
||||
do {
|
||||
old_val = static_cast<__int64>(*x);
|
||||
new_val = old_val - static_cast<__int64>(1);
|
||||
} while (_InterlockedCompareExchange64(
|
||||
reinterpret_cast<volatile __int64*>(x), new_val, old_val) !=
|
||||
old_val);
|
||||
return static_cast<T>(new_val);
|
||||
#endif // _M_X64
|
||||
}
|
||||
|
||||
static inline T compare_exchange(T volatile* x,
|
||||
const T new_val,
|
||||
const T expected_val) {
|
||||
return static_cast<T>(_InterlockedCompareExchange64(
|
||||
reinterpret_cast<volatile __int64*>(x),
|
||||
static_cast<const __int64>(new_val),
|
||||
static_cast<const __int64>(expected_val)));
|
||||
}
|
||||
|
||||
static inline T exchange(T volatile* x, const T new_val) {
|
||||
#if defined(_M_X64)
|
||||
return static_cast<T>(
|
||||
_InterlockedExchange64(reinterpret_cast<volatile __int64*>(x),
|
||||
static_cast<const __int64>(new_val)));
|
||||
#else
|
||||
// There's no _InterlockedExchange64 for 32-bit x86.
|
||||
__int64 old_val;
|
||||
do {
|
||||
old_val = static_cast<__int64>(*x);
|
||||
} while (_InterlockedCompareExchange64(
|
||||
reinterpret_cast<volatile __int64*>(x), new_val, old_val) !=
|
||||
old_val);
|
||||
return static_cast<T>(old_val);
|
||||
#endif // _M_X64
|
||||
}
|
||||
};
|
||||
} // namespace msvc
|
||||
} // namespace sync
|
||||
} // namespace srt
|
||||
|
||||
#endif // ATOMIC_ATOMIC_MSVC_H_
|
1955
trunk/3rdparty/srt-1-fit/srtcore/buffer.cpp
vendored
1955
trunk/3rdparty/srt-1-fit/srtcore/buffer.cpp
vendored
File diff suppressed because it is too large
Load diff
510
trunk/3rdparty/srt-1-fit/srtcore/buffer.h
vendored
510
trunk/3rdparty/srt-1-fit/srtcore/buffer.h
vendored
|
@ -1,510 +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 __UDT_BUFFER_H__
|
||||
#define __UDT_BUFFER_H__
|
||||
|
||||
|
||||
#include "udt.h"
|
||||
#include "list.h"
|
||||
#include "queue.h"
|
||||
#include "utilities.h"
|
||||
#include <fstream>
|
||||
|
||||
class CSndBuffer
|
||||
{
|
||||
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 ""; }
|
||||
|
||||
CSndBuffer(int size = 32, int mss = 1500);
|
||||
~CSndBuffer();
|
||||
|
||||
public:
|
||||
|
||||
/// Insert a user buffer into the sending list.
|
||||
/// @param [in] data pointer to the user data block.
|
||||
/// @param [in] len size of the block.
|
||||
/// @param [in] ttl time to live in milliseconds
|
||||
/// @param [in] order if the block should be delivered in order, for DGRAM only
|
||||
|
||||
void addBuffer(const char* data, int len, int ttl, bool order, uint64_t srctime, ref_t<int32_t> r_msgno);
|
||||
|
||||
/// 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.
|
||||
|
||||
int addBufferFromFile(std::fstream& ifs, int len);
|
||||
|
||||
/// Find data position to pack a DATA packet from the furthest reading point.
|
||||
/// @param [out] data the pointer to the data position.
|
||||
/// @param [out] msgno message number of the packet.
|
||||
/// @param [out] origintime origin time stamp of the message
|
||||
/// @param [in] kflags Odd|Even crypto key flag
|
||||
/// @return Actual length of data read.
|
||||
|
||||
int readData(char** data, int32_t& msgno, uint64_t& origintime, int kflgs);
|
||||
|
||||
|
||||
/// Find data position to pack a DATA packet for a retransmission.
|
||||
/// @param [out] data the pointer to the data position.
|
||||
/// @param [in] offset offset from the last ACK point.
|
||||
/// @param [out] msgno message number of the packet.
|
||||
/// @param [out] origintime origin time stamp of the message
|
||||
/// @param [out] msglen length of the message
|
||||
/// @return Actual length of data read.
|
||||
|
||||
int readData(char** data, const int offset, int32_t& msgno, uint64_t& origintime, int& msglen);
|
||||
|
||||
/// Update the ACK point and may release/unmap/return the user data according to the flag.
|
||||
/// @param [in] offset number of packets acknowledged.
|
||||
|
||||
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;
|
||||
|
||||
int dropLateData(int &bytes, uint64_t latetime);
|
||||
|
||||
#ifdef SRT_ENABLE_SNDBUFSZ_MAVG
|
||||
void updAvgBufSize(uint64_t time);
|
||||
int getAvgBufSize(ref_t<int> bytes, ref_t<int> timespan);
|
||||
#endif /* SRT_ENABLE_SNDBUFSZ_MAVG */
|
||||
int getCurrBufSize(ref_t<int> bytes, ref_t<int> timespan);
|
||||
|
||||
uint64_t getInRatePeriod() const { return m_InRatePeriod; }
|
||||
|
||||
/// Retrieve input bitrate in bytes per second
|
||||
int getInputRate() const { return m_iInRateBps; }
|
||||
|
||||
/// 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(uint64_t time, int pkts = 0, int bytes = 0);
|
||||
|
||||
|
||||
void resetInputRateSmpPeriod(bool disable = false)
|
||||
{
|
||||
setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void increase();
|
||||
void setInputRateSmpPeriod(int period);
|
||||
|
||||
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:
|
||||
pthread_mutex_t m_BufLock; // used to synchronize buffer operation
|
||||
|
||||
struct Block
|
||||
{
|
||||
char* m_pcData; // pointer to the data block
|
||||
int m_iLength; // length of the block
|
||||
|
||||
int32_t m_iMsgNoBitset; // message number
|
||||
uint64_t m_ullOriginTime_us; // original request time
|
||||
uint64_t m_ullSourceTime_us;
|
||||
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)
|
||||
int m_iMSS; // maximum seqment/packet size
|
||||
|
||||
int m_iCount; // number of used blocks
|
||||
|
||||
int m_iBytesCount; // number of payload bytes in queue
|
||||
uint64_t m_ullLastOriginTime_us;
|
||||
|
||||
#ifdef SRT_ENABLE_SNDBUFSZ_MAVG
|
||||
uint64_t m_LastSamplingTime;
|
||||
int m_iCountMAvg;
|
||||
int m_iBytesCountMAvg;
|
||||
int m_TimespanMAvg;
|
||||
#endif /* SRT_ENABLE_SNDBUFSZ_MAVG */
|
||||
|
||||
int m_iInRatePktsCount; // number of payload bytes added since InRateStartTime
|
||||
int m_iInRateBytesCount; // number of payload bytes added since InRateStartTime
|
||||
uint64_t m_InRateStartTime;
|
||||
uint64_t m_InRatePeriod; // usec
|
||||
int m_iInRateBps; // Input Rate in Bytes/sec
|
||||
int m_iAvgPayloadSz; // Average packet payload size
|
||||
|
||||
private:
|
||||
CSndBuffer(const CSndBuffer&);
|
||||
CSndBuffer& operator=(const CSndBuffer&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class CRcvBuffer
|
||||
{
|
||||
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 ""; }
|
||||
|
||||
|
||||
/// 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 = 65536);
|
||||
~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.
|
||||
|
||||
void 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);
|
||||
#if SRT_ENABLE_RCVBUFSZ_MAVG
|
||||
|
||||
/// 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(uint64_t now);
|
||||
#endif /* SRT_ENABLE_RCVBUFSZ_MAVG */
|
||||
|
||||
/// Query the received average payload size.
|
||||
/// @return size (bytes) of payload size
|
||||
|
||||
int getRcvAvgPayloadSize() 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);
|
||||
|
||||
/// 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, ref_t<SRT_MSGCTRL> mctrl);
|
||||
|
||||
/// 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(ref_t<uint64_t> tsbpdtime, ref_t<int32_t> curpktseq);
|
||||
bool isRcvDataReady();
|
||||
bool isRcvDataAvailable()
|
||||
{
|
||||
return m_iLastAckPos != m_iStartPos;
|
||||
}
|
||||
CPacket* getRcvReadyPacket();
|
||||
|
||||
/// 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
|
||||
/// @return 0
|
||||
|
||||
int setRcvTsbPdMode(uint64_t timebase, uint32_t delay);
|
||||
|
||||
/// Add packet timestamp for drift caclculation and compensation
|
||||
/// @param [in] timestamp packet time stamp
|
||||
/// @param [ref] lock Mutex that should be locked for the operation
|
||||
|
||||
void addRcvTsbPdDriftSample(uint32_t timestamp, pthread_mutex_t& lock);
|
||||
|
||||
#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] 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.
|
||||
/// @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, no missing packet but 1st not ready to play.
|
||||
|
||||
|
||||
bool getRcvFirstMsg(ref_t<uint64_t> tsbpdtime, ref_t<bool> passack, ref_t<int32_t> skipseqno, ref_t<int32_t> curpktseq);
|
||||
|
||||
/// 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(); // Heavy logging Debug only
|
||||
#endif
|
||||
|
||||
private:
|
||||
/// 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
|
||||
/// @retval true 1st packet ready to play without discontinuity (no hole)
|
||||
/// @retval false tsbpdtime = 0: no packet ready to play
|
||||
|
||||
|
||||
bool getRcvReadyMsg(ref_t<uint64_t> tsbpdtime, ref_t<int32_t> curpktseq);
|
||||
|
||||
public:
|
||||
|
||||
// (This is exposed as used publicly in logs)
|
||||
/// Get packet delivery local time base (adjusted for wrap around)
|
||||
/// @param [in] timestamp packet timestamp (relative to peer StartTime), wrapping around every ~72 min
|
||||
/// @return local delivery time (usec)
|
||||
uint64_t getTsbPdTimeBase(uint32_t timestamp_us);
|
||||
|
||||
/// Get packet local delivery time
|
||||
/// @param [in] timestamp packet timestamp (relative to peer StartTime), wrapping around every ~72 min
|
||||
/// @return local delivery time (usec)
|
||||
|
||||
public:
|
||||
uint64_t getPktTsbPdTime(uint32_t timestamp);
|
||||
int debugGetSize() const;
|
||||
bool empty() const;
|
||||
|
||||
// Required by PacketFilter facility to use as a storage
|
||||
// for provided packets
|
||||
CUnitQueue* getUnitQueue()
|
||||
{
|
||||
return m_pUnitQueue;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// 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(ref_t<int> start, ref_t<int> end, ref_t<bool> passack);
|
||||
|
||||
private:
|
||||
CUnit** m_pUnit; // pointer to the protocol buffer (array of CUnit* items)
|
||||
const int m_iSize; // size of the array of CUnit* items
|
||||
CUnitQueue* m_pUnitQueue; // the shared unit queue
|
||||
|
||||
int m_iStartPos; // the head position for I/O (inclusive)
|
||||
int m_iLastAckPos; // the last ACKed position (exclusive)
|
||||
// EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1
|
||||
int m_iMaxPos; // the furthest data position
|
||||
|
||||
int m_iNotch; // the starting read point of the first unit
|
||||
|
||||
pthread_mutex_t 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
|
||||
int m_iAvgPayloadSz; // Average payload size for dropped bytes estimation
|
||||
|
||||
bool m_bTsbPdMode; // true: apply TimeStamp-Based Rx Mode
|
||||
uint32_t m_uTsbPdDelay; // aggreed delay
|
||||
uint64_t m_ullTsbPdTimeBase; // localtime base for TsbPd mode
|
||||
// Note: m_ullTsbPdTimeBase cumulates values from:
|
||||
// 1. Initial SRT_CMD_HSREQ packet returned value diff to current time:
|
||||
// == (NOW - PACKET_TIMESTAMP), at the time of HSREQ reception
|
||||
// 2. Timestamp overflow (@c CRcvBuffer::getTsbPdTimeBase), when overflow on packet detected
|
||||
// += CPacket::MAX_TIMESTAMP+1 (it's a hex round value, usually 0x1*e8).
|
||||
// 3. Time drift (CRcvBuffer::addRcvTsbPdDriftSample, executed exclusively
|
||||
// from UMSG_ACKACK handler). This is updated with (positive or negative) TSBPD_DRIFT_MAX_VALUE
|
||||
// once the value of average drift exceeds this value in whatever direction.
|
||||
// += (+/-)CRcvBuffer::TSBPD_DRIFT_MAX_VALUE
|
||||
//
|
||||
// XXX Application-supplied timestamps won't work therefore. This requires separate
|
||||
// calculation of all these things above.
|
||||
|
||||
bool m_bTsbPdWrapCheck; // true: check packet time stamp wrap around
|
||||
static const uint32_t TSBPD_WRAP_PERIOD = (30*1000000); //30 seconds (in usec)
|
||||
|
||||
static const int TSBPD_DRIFT_MAX_VALUE = 5000; // Max drift (usec) above which TsbPD Time Offset is adjusted
|
||||
static const int TSBPD_DRIFT_MAX_SAMPLES = 1000; // Number of samples (UMSG_ACKACK packets) to perform drift caclulation and compensation
|
||||
//int m_iTsbPdDrift; // recent drift in the packet time stamp
|
||||
//int64_t m_TsbPdDriftSum; // Sum of sampled drift
|
||||
//int m_iTsbPdDriftNbSamples; // Number of samples in sum and histogram
|
||||
DriftTracer<TSBPD_DRIFT_MAX_SAMPLES, TSBPD_DRIFT_MAX_VALUE> m_DriftTracer;
|
||||
#ifdef SRT_ENABLE_RCVBUFSZ_MAVG
|
||||
uint64_t m_LastSamplingTime;
|
||||
int m_TimespanMAvg;
|
||||
int m_iCountMAvg;
|
||||
int m_iBytesCountMAvg;
|
||||
#endif /* SRT_ENABLE_RCVBUFSZ_MAVG */
|
||||
#ifdef SRT_DEBUG_TSBPD_DRIFT
|
||||
int m_TsbPdDriftHisto100us[22]; // Histogram of 100us TsbPD drift (-1.0 .. +1.0 ms in 0.1ms increment)
|
||||
int m_TsbPdDriftHisto1ms[22]; // Histogram of TsbPD drift (-10.0 .. +10.0 ms, in 1.0 ms increment)
|
||||
static const int TSBPD_DRIFT_PRT_SAMPLES = 200; // Number of samples (UMSG_ACKACK packets) to print hostogram
|
||||
#endif /* SRT_DEBUG_TSBPD_DRIFT */
|
||||
|
||||
#ifdef SRT_DEBUG_TSBPD_OUTJITTER
|
||||
unsigned long m_ulPdHisto[4][10];
|
||||
#endif /* SRT_DEBUG_TSBPD_OUTJITTER */
|
||||
|
||||
private:
|
||||
CRcvBuffer();
|
||||
CRcvBuffer(const CRcvBuffer&);
|
||||
CRcvBuffer& operator=(const CRcvBuffer&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
1153
trunk/3rdparty/srt-1-fit/srtcore/buffer_rcv.cpp
vendored
Normal file
1153
trunk/3rdparty/srt-1-fit/srtcore/buffer_rcv.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
392
trunk/3rdparty/srt-1-fit/srtcore/buffer_rcv.h
vendored
Normal file
392
trunk/3rdparty/srt-1-fit/srtcore/buffer_rcv.h
vendored
Normal file
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* SRT - Secure, Reliable, Transport
|
||||
* Copyright (c) 2020 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_BUFFER_RCV_H
|
||||
#define INC_SRT_BUFFER_RCV_H
|
||||
|
||||
#include "buffer_tools.h" // AvgBufSize
|
||||
#include "common.h"
|
||||
#include "queue.h"
|
||||
#include "tsbpd_time.h"
|
||||
|
||||
namespace srt
|
||||
{
|
||||
|
||||
/*
|
||||
* Circular receiver buffer.
|
||||
*
|
||||
* |<------------------- m_szSize ---------------------------->|
|
||||
* | |<------------ m_iMaxPosOff ----------->| |
|
||||
* | | | |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+
|
||||
* | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |...| 0 | m_pUnit[]
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+
|
||||
* | |
|
||||
* | \__last pkt received
|
||||
* |
|
||||
* \___ m_iStartPos: first message to read
|
||||
*
|
||||
* m_pUnit[i]->status_: 0: free, 1: good, 2: read, 3: dropped (can be combined with read?)
|
||||
*
|
||||
* thread safety:
|
||||
* start_pos_: CUDT::m_RecvLock
|
||||
* first_unack_pos_: CUDT::m_AckLock
|
||||
* max_pos_inc_: none? (modified on add and ack
|
||||
* first_nonread_pos_:
|
||||
*/
|
||||
|
||||
class CRcvBuffer
|
||||
{
|
||||
typedef sync::steady_clock::time_point time_point;
|
||||
typedef sync::steady_clock::duration duration;
|
||||
|
||||
public:
|
||||
CRcvBuffer(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI);
|
||||
|
||||
~CRcvBuffer();
|
||||
|
||||
public:
|
||||
/// Insert a unit into the buffer.
|
||||
/// Similar to CRcvBuffer::addData(CUnit* unit, int offset)
|
||||
///
|
||||
/// @param [in] unit pointer to a data unit containing new packet
|
||||
/// @param [in] offset offset from last ACK point.
|
||||
///
|
||||
/// @return 0 on success, -1 if packet is already in buffer, -2 if packet is before m_iStartSeqNo.
|
||||
/// -3 if a packet is offset is ahead the buffer capacity.
|
||||
// TODO: Previously '-2' also meant 'already acknowledged'. Check usage of this value.
|
||||
int insert(CUnit* unit);
|
||||
|
||||
/// Drop packets in the receiver buffer from the current position up to the seqno (excluding seqno).
|
||||
/// @param [in] seqno drop units up to this sequence number
|
||||
/// @return number of dropped packets.
|
||||
int dropUpTo(int32_t seqno);
|
||||
|
||||
/// @brief Drop all the packets in the receiver buffer.
|
||||
/// The starting position and seqno are shifted right after the last packet in the buffer.
|
||||
/// @return the number of dropped packets.
|
||||
int dropAll();
|
||||
|
||||
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, DropActionIfExists actionOnExisting);
|
||||
|
||||
/// Read the whole message from one or several packets.
|
||||
///
|
||||
/// @param [in,out] data buffer to write the message into.
|
||||
/// @param [in] len size of the buffer.
|
||||
/// @param [in,out] message control data
|
||||
///
|
||||
/// @return actual number of bytes extracted from the buffer.
|
||||
/// 0 if nothing to read.
|
||||
/// -1 on failure.
|
||||
int readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl = NULL);
|
||||
|
||||
/// Read acknowledged data into a user buffer.
|
||||
/// @param [in, out] dst pointer to the target user buffer.
|
||||
/// @param [in] len length of user buffer.
|
||||
/// @return size of data read. -1 on error.
|
||||
int readBuffer(char* dst, int len);
|
||||
|
||||
/// Read acknowledged data directly into file.
|
||||
/// @param [in] ofs C++ file stream.
|
||||
/// @param [in] len expected length of data to write into the file.
|
||||
/// @return size of data read. -1 on error.
|
||||
int readBufferToFile(std::fstream& ofs, int len);
|
||||
|
||||
public:
|
||||
/// Get the starting position of the buffer as a packet sequence number.
|
||||
int getStartSeqNo() const { return m_iStartSeqNo; }
|
||||
|
||||
/// Sets the start seqno of the buffer.
|
||||
/// Must be used with caution and only when the buffer is empty.
|
||||
void setStartSeqNo(int seqno) { m_iStartSeqNo = seqno; }
|
||||
|
||||
/// Given the sequence number of the first unacknowledged packet
|
||||
/// tells the size of the buffer available for packets.
|
||||
/// Effective returns capacity of the buffer minus acknowledged packet still kept in it.
|
||||
// TODO: Maybe does not need to return minus one slot now to distinguish full and empty buffer.
|
||||
size_t getAvailSize(int iFirstUnackSeqNo) const
|
||||
{
|
||||
// Receiver buffer allows reading unacknowledged packets.
|
||||
// Therefore if the first packet in the buffer is ahead of the iFirstUnackSeqNo
|
||||
// then it does not have acknowledged packets and its full capacity is available.
|
||||
// Otherwise subtract the number of acknowledged but not yet read packets from its capacity.
|
||||
const int iRBufSeqNo = getStartSeqNo();
|
||||
if (CSeqNo::seqcmp(iRBufSeqNo, iFirstUnackSeqNo) >= 0) // iRBufSeqNo >= iFirstUnackSeqNo
|
||||
{
|
||||
// Full capacity is available.
|
||||
return capacity();
|
||||
}
|
||||
|
||||
// Note: CSeqNo::seqlen(n, n) returns 1.
|
||||
return capacity() - CSeqNo::seqlen(iRBufSeqNo, iFirstUnackSeqNo) + 1;
|
||||
}
|
||||
|
||||
/// @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 (continuous) data for reading.
|
||||
int getRcvDataSize() const;
|
||||
|
||||
/// Get the number of packets, bytes and buffer timespan.
|
||||
/// Differs from getRcvDataSize() that it counts all packets in the buffer, not only continious.
|
||||
int getRcvDataSize(int& bytes, int& timespan) const;
|
||||
|
||||
struct PacketInfo
|
||||
{
|
||||
int seqno;
|
||||
bool seq_gap; //< true if there are missing packets in the buffer, preceding current packet
|
||||
time_point tsbpd_time;
|
||||
};
|
||||
|
||||
/// Get information on the 1st message in queue.
|
||||
/// Similar to CRcvBuffer::getRcvFirstMsg
|
||||
/// 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 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 preceded by missing packets.;
|
||||
/// IF skipseqno == -1, no missing packet but 1st not ready to play.
|
||||
PacketInfo getFirstValidPacketInfo() const;
|
||||
|
||||
PacketInfo getFirstReadablePacketInfo(time_point time_now) const;
|
||||
|
||||
/// Get information on packets available to be read.
|
||||
/// @returns a pair of sequence numbers (first available; first unavailable).
|
||||
///
|
||||
/// @note CSeqNo::seqoff(first, second) is 0 if nothing to read.
|
||||
std::pair<int, int> getAvailablePacketsRange() const;
|
||||
|
||||
size_t countReadable() const;
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (m_iMaxPosOff == 0);
|
||||
}
|
||||
|
||||
/// Return buffer capacity.
|
||||
/// One slot had to be empty in order to tell the difference between "empty buffer" and "full buffer".
|
||||
/// E.g. m_iFirstNonreadPos would again point to m_iStartPos if m_szSize entries are added continiously.
|
||||
/// TODO: Old receiver buffer capacity returns the actual size. Check for conflicts.
|
||||
size_t capacity() const
|
||||
{
|
||||
return m_szSize - 1;
|
||||
}
|
||||
|
||||
int64_t getDrift() const { return m_tsbpd.drift(); }
|
||||
|
||||
// TODO: make thread safe?
|
||||
int debugGetSize() const
|
||||
{
|
||||
return getRcvDataSize();
|
||||
}
|
||||
|
||||
/// Zero time to include all available packets.
|
||||
/// TODO: Rename to 'canRead`.
|
||||
bool isRcvDataReady(time_point time_now = time_point()) const;
|
||||
|
||||
int getRcvAvgDataSize(int& bytes, int& timespan);
|
||||
void updRcvAvgDataSize(const time_point& now);
|
||||
|
||||
unsigned getRcvAvgPayloadSize() const { return m_uAvgPayloadSz; }
|
||||
|
||||
void getInternalTimeBase(time_point& w_timebase, bool& w_wrp, duration& w_udrift)
|
||||
{
|
||||
return m_tsbpd.getInternalTimeBase(w_timebase, w_wrp, w_udrift);
|
||||
}
|
||||
|
||||
public: // Used for testing
|
||||
/// Peek unit in position of seqno
|
||||
const CUnit* peek(int32_t seqno);
|
||||
|
||||
private:
|
||||
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);
|
||||
void updateNonreadPos();
|
||||
void releaseUnitInPos(int pos);
|
||||
|
||||
/// @brief Drop a unit from the buffer.
|
||||
/// @param pos position in the m_entries of the unit to drop.
|
||||
/// @return false if nothing to drop, true if the unit was dropped successfully.
|
||||
bool dropUnitInPos(int pos);
|
||||
|
||||
/// Release entries following the current buffer position if they were already
|
||||
/// read out of order (EntryState_Read) or dropped (EntryState_Drop).
|
||||
void releaseNextFillerEntries();
|
||||
|
||||
bool hasReadableInorderPkts() const { return (m_iFirstNonreadPos != m_iStartPos); }
|
||||
|
||||
/// Find position of the last packet of the message.
|
||||
int findLastMessagePkt();
|
||||
|
||||
/// Scan for availability of out of order packets.
|
||||
void onInsertNotInOrderPacket(int insertpos);
|
||||
// Check if m_iFirstReadableOutOfOrder is still readable.
|
||||
bool checkFirstReadableOutOfOrder();
|
||||
void updateFirstReadableOutOfOrder();
|
||||
int scanNotInOrderMessageRight(int startPos, int msgNo) const;
|
||||
int scanNotInOrderMessageLeft(int startPos, int msgNo) const;
|
||||
|
||||
typedef bool copy_to_dst_f(char* data, int len, int dst_offset, void* arg);
|
||||
|
||||
/// Read acknowledged data directly into file.
|
||||
/// @param [in] ofs C++ file stream.
|
||||
/// @param [in] len expected length of data to write into the file.
|
||||
/// @return size of data read.
|
||||
int readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg);
|
||||
|
||||
/// @brief Estimate timespan of the stored packets (acknowledged and unacknowledged).
|
||||
/// @return timespan in milliseconds
|
||||
int getTimespan_ms() const;
|
||||
|
||||
private:
|
||||
// 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
|
||||
// {
|
||||
// public:
|
||||
// void operator=(CUnit* pUnit)
|
||||
// {
|
||||
// if (m_pUnit != NULL)
|
||||
// {
|
||||
// // m_pUnitQueue->makeUnitFree(m_entries[i].pUnit);
|
||||
// }
|
||||
// m_pUnit = pUnit;
|
||||
// }
|
||||
// private:
|
||||
// CUnit* m_pUnit;
|
||||
// };
|
||||
|
||||
enum EntryStatus
|
||||
{
|
||||
EntryState_Empty, //< No CUnit record.
|
||||
EntryState_Avail, //< Entry is available for reading.
|
||||
EntryState_Read, //< Entry has already been read (out of order).
|
||||
EntryState_Drop //< Entry has been dropped.
|
||||
};
|
||||
struct Entry
|
||||
{
|
||||
Entry()
|
||||
: pUnit(NULL)
|
||||
, status(EntryState_Empty)
|
||||
{}
|
||||
|
||||
CUnit* pUnit;
|
||||
EntryStatus status;
|
||||
};
|
||||
|
||||
//static Entry emptyEntry() { return Entry { NULL, EntryState_Empty }; }
|
||||
|
||||
FixedArray<Entry> m_entries;
|
||||
|
||||
const size_t m_szSize; // size of the array of units (buffer)
|
||||
CUnitQueue* m_pUnitQueue; // the shared unit queue
|
||||
|
||||
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_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
|
||||
int m_iFirstReadableOutOfOrder; // In case of out ouf order packet, points to a position of the first such packet to
|
||||
// read
|
||||
bool m_bPeerRexmitFlag; // Needed to read message number correctly
|
||||
const bool m_bMessageAPI; // Operation mode flag: message or stream.
|
||||
|
||||
public: // TSBPD public functions
|
||||
/// 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 agreed TsbPD delay
|
||||
///
|
||||
/// @return 0
|
||||
void setTsbPdMode(const time_point& timebase, bool wrap, duration delay);
|
||||
|
||||
void setPeerRexmitFlag(bool flag) { m_bPeerRexmitFlag = flag; }
|
||||
|
||||
void applyGroupTime(const time_point& timebase, bool wrp, uint32_t delay, const duration& udrift);
|
||||
|
||||
void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift);
|
||||
|
||||
bool addRcvTsbPdDriftSample(uint32_t usTimestamp, const time_point& tsPktArrival, int usRTTSample);
|
||||
|
||||
time_point getPktTsbPdTime(uint32_t usPktTimestamp) const;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
CTsbpdTime m_tsbpd;
|
||||
|
||||
private: // Statistics
|
||||
AvgBufSize m_mavg;
|
||||
|
||||
// TODO: m_BytesCountLock is probably not needed as the buffer has to be protected from simultaneous access.
|
||||
mutable sync::Mutex m_BytesCountLock; // used to protect counters operations
|
||||
int m_iBytesCount; // Number of payload bytes in the buffer
|
||||
int m_iPktsCount; // Number of payload bytes in the buffer
|
||||
unsigned m_uAvgPayloadSz; // Average payload size for dropped bytes estimation
|
||||
};
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif // INC_SRT_BUFFER_RCV_H
|
730
trunk/3rdparty/srt-1-fit/srtcore/buffer_snd.cpp
vendored
Normal file
730
trunk/3rdparty/srt-1-fit/srtcore/buffer_snd.cpp
vendored
Normal file
|
@ -0,0 +1,730 @@
|
|||
/*
|
||||
* 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 03/12/2011
|
||||
modified by
|
||||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "platform_sys.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "buffer_snd.h"
|
||||
#include "packet.h"
|
||||
#include "core.h" // provides some constants
|
||||
#include "logging.h"
|
||||
|
||||
namespace srt {
|
||||
|
||||
using namespace std;
|
||||
using namespace srt_logging;
|
||||
using namespace sync;
|
||||
|
||||
CSndBuffer::CSndBuffer(int size, int maxpld, int authtag)
|
||||
: m_BufLock()
|
||||
, m_pBlock(NULL)
|
||||
, m_pFirstBlock(NULL)
|
||||
, m_pCurrBlock(NULL)
|
||||
, m_pLastBlock(NULL)
|
||||
, m_pBuffer(NULL)
|
||||
, m_iNextMsgNo(1)
|
||||
, m_iSize(size)
|
||||
, m_iBlockLen(maxpld)
|
||||
, m_iAuthTagSize(authtag)
|
||||
, m_iCount(0)
|
||||
, m_iBytesCount(0)
|
||||
{
|
||||
// initial physical buffer of "size"
|
||||
m_pBuffer = new Buffer;
|
||||
m_pBuffer->m_pcData = new char[m_iSize * m_iBlockLen];
|
||||
m_pBuffer->m_iSize = m_iSize;
|
||||
m_pBuffer->m_pNext = NULL;
|
||||
|
||||
// circular linked list for out bound packets
|
||||
m_pBlock = new Block;
|
||||
Block* pb = m_pBlock;
|
||||
char* pc = m_pBuffer->m_pcData;
|
||||
|
||||
for (int i = 0; i < m_iSize; ++i)
|
||||
{
|
||||
pb->m_iMsgNoBitset = 0;
|
||||
pb->m_pcData = pc;
|
||||
pc += m_iBlockLen;
|
||||
|
||||
if (i < m_iSize - 1)
|
||||
{
|
||||
pb->m_pNext = new Block;
|
||||
pb = pb->m_pNext;
|
||||
}
|
||||
}
|
||||
pb->m_pNext = m_pBlock;
|
||||
|
||||
m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock;
|
||||
|
||||
setupMutex(m_BufLock, "Buf");
|
||||
}
|
||||
|
||||
CSndBuffer::~CSndBuffer()
|
||||
{
|
||||
Block* pb = m_pBlock->m_pNext;
|
||||
while (pb != m_pBlock)
|
||||
{
|
||||
Block* temp = pb;
|
||||
pb = pb->m_pNext;
|
||||
delete temp;
|
||||
}
|
||||
delete m_pBlock;
|
||||
|
||||
while (m_pBuffer != NULL)
|
||||
{
|
||||
Buffer* temp = m_pBuffer;
|
||||
m_pBuffer = m_pBuffer->m_pNext;
|
||||
delete[] temp->m_pcData;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
releaseMutex(m_BufLock);
|
||||
}
|
||||
|
||||
void CSndBuffer::addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl)
|
||||
{
|
||||
int32_t& w_msgno = w_mctrl.msgno;
|
||||
int32_t& w_seqno = w_mctrl.pktseq;
|
||||
int64_t& w_srctime = w_mctrl.srctime;
|
||||
const int& ttl = w_mctrl.msgttl;
|
||||
const int iPktLen = getMaxPacketLen();
|
||||
const int iNumBlocks = countNumPacketsRequired(len, iPktLen);
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "addBuffer: needs=" << iNumBlocks << " buffers for " << len << " bytes. Taken=" << m_iCount << "/" << m_iSize);
|
||||
// Retrieve current time before locking the mutex to be closer to packet submission event.
|
||||
const steady_clock::time_point tnow = steady_clock::now();
|
||||
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
// Dynamically increase sender buffer if there is not enough room.
|
||||
while (iNumBlocks + m_iCount >= m_iSize)
|
||||
{
|
||||
HLOGC(bslog.Debug, log << "addBuffer: ... still lacking " << (iNumBlocks + m_iCount - m_iSize) << " buffers...");
|
||||
increase();
|
||||
}
|
||||
|
||||
const int32_t inorder = w_mctrl.inorder ? MSGNO_PACKET_INORDER::mask : 0;
|
||||
HLOGC(bslog.Debug,
|
||||
log << CONID() << "addBuffer: adding " << iNumBlocks << " packets (" << len << " bytes) to send, msgno="
|
||||
<< (w_msgno > 0 ? w_msgno : m_iNextMsgNo) << (inorder ? "" : " NOT") << " in order");
|
||||
|
||||
// Calculate origin time (same for all blocks of the message).
|
||||
m_tsLastOriginTime = w_srctime ? time_point() + microseconds_from(w_srctime) : tnow;
|
||||
// Rewrite back the actual value, even if it stays the same, so that the calling facilities can reuse it.
|
||||
// May also be a subject to conversion error, thus the actual value is signalled back.
|
||||
w_srctime = count_microseconds(m_tsLastOriginTime.time_since_epoch());
|
||||
|
||||
// The sequence number passed to this function is the sequence number
|
||||
// that the very first packet from the packet series should get here.
|
||||
// If there's more than one packet, this function must increase it by itself
|
||||
// and then return the accordingly modified sequence number in the reference.
|
||||
|
||||
Block* s = m_pLastBlock;
|
||||
|
||||
if (w_msgno == SRT_MSGNO_NONE) // DEFAULT-UNCHANGED msgno supplied
|
||||
{
|
||||
HLOGC(bslog.Debug, log << "addBuffer: using internally managed msgno=" << m_iNextMsgNo);
|
||||
w_msgno = m_iNextMsgNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(bslog.Debug, log << "addBuffer: OVERWRITTEN by msgno supplied by caller: msgno=" << w_msgno);
|
||||
m_iNextMsgNo = w_msgno;
|
||||
}
|
||||
|
||||
for (int i = 0; i < iNumBlocks; ++i)
|
||||
{
|
||||
int pktlen = len - i * iPktLen;
|
||||
if (pktlen > iPktLen)
|
||||
pktlen = iPktLen;
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "addBuffer: %" << w_seqno << " #" << w_msgno << " offset=" << (i * iPktLen)
|
||||
<< " size=" << pktlen << " TO BUFFER:" << (void*)s->m_pcData);
|
||||
memcpy((s->m_pcData), data + i * iPktLen, pktlen);
|
||||
s->m_iLength = pktlen;
|
||||
|
||||
s->m_iSeqNo = w_seqno;
|
||||
w_seqno = CSeqNo::incseq(w_seqno);
|
||||
|
||||
s->m_iMsgNoBitset = m_iNextMsgNo | inorder;
|
||||
if (i == 0)
|
||||
s->m_iMsgNoBitset |= PacketBoundaryBits(PB_FIRST);
|
||||
if (i == iNumBlocks - 1)
|
||||
s->m_iMsgNoBitset |= PacketBoundaryBits(PB_LAST);
|
||||
// NOTE: if i is neither 0 nor size-1, it resuls with PB_SUBSEQUENT.
|
||||
// if i == 0 == size-1, it results with PB_SOLO.
|
||||
// Packets assigned to one message can be:
|
||||
// [PB_FIRST] [PB_SUBSEQUENT] [PB_SUBSEQUENT] [PB_LAST] - 4 packets per message
|
||||
// [PB_FIRST] [PB_LAST] - 2 packets per message
|
||||
// [PB_SOLO] - 1 packet per message
|
||||
|
||||
s->m_iTTL = ttl;
|
||||
s->m_tsRexmitTime = time_point();
|
||||
s->m_tsOriginTime = m_tsLastOriginTime;
|
||||
|
||||
// Should never happen, as the call to increase() should ensure enough buffers.
|
||||
SRT_ASSERT(s->m_pNext);
|
||||
s = s->m_pNext;
|
||||
}
|
||||
m_pLastBlock = s;
|
||||
|
||||
m_iCount += iNumBlocks;
|
||||
m_iBytesCount += len;
|
||||
|
||||
m_rateEstimator.updateInputRate(m_tsLastOriginTime, iNumBlocks, len);
|
||||
updAvgBufSize(m_tsLastOriginTime);
|
||||
|
||||
// MSGNO_SEQ::mask has a form: 00000011111111...
|
||||
// At least it's known that it's from some index inside til the end (to bit 0).
|
||||
// If this value has been reached in a step of incrementation, it means that the
|
||||
// maximum value has been reached. Casting to int32_t to ensure the same sign
|
||||
// in comparison, although it's far from reaching the sign bit.
|
||||
|
||||
const int nextmsgno = ++MsgNo(m_iNextMsgNo);
|
||||
HLOGC(bslog.Debug, log << "CSndBuffer::addBuffer: updating msgno: #" << m_iNextMsgNo << " -> #" << nextmsgno);
|
||||
m_iNextMsgNo = nextmsgno;
|
||||
}
|
||||
|
||||
int CSndBuffer::addBufferFromFile(fstream& ifs, int len)
|
||||
{
|
||||
const int iPktLen = getMaxPacketLen();
|
||||
const int iNumBlocks = countNumPacketsRequired(len, iPktLen);
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "addBufferFromFile: size=" << m_iCount << " reserved=" << m_iSize << " needs=" << iPktLen
|
||||
<< " buffers for " << len << " bytes");
|
||||
|
||||
// dynamically increase sender buffer
|
||||
while (iNumBlocks + m_iCount >= m_iSize)
|
||||
{
|
||||
HLOGC(bslog.Debug,
|
||||
log << "addBufferFromFile: ... still lacking " << (iNumBlocks + m_iCount - m_iSize) << " buffers...");
|
||||
increase();
|
||||
}
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << CONID() << "addBufferFromFile: adding " << iPktLen << " packets (" << len
|
||||
<< " bytes) to send, msgno=" << m_iNextMsgNo);
|
||||
|
||||
Block* s = m_pLastBlock;
|
||||
int total = 0;
|
||||
for (int i = 0; i < iNumBlocks; ++i)
|
||||
{
|
||||
if (ifs.bad() || ifs.fail() || ifs.eof())
|
||||
break;
|
||||
|
||||
int pktlen = len - i * iPktLen;
|
||||
if (pktlen > iPktLen)
|
||||
pktlen = iPktLen;
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "addBufferFromFile: reading from=" << (i * iPktLen) << " size=" << pktlen
|
||||
<< " TO BUFFER:" << (void*)s->m_pcData);
|
||||
ifs.read(s->m_pcData, pktlen);
|
||||
if ((pktlen = int(ifs.gcount())) <= 0)
|
||||
break;
|
||||
|
||||
// currently file transfer is only available in streaming mode, message is always in order, ttl = infinite
|
||||
s->m_iMsgNoBitset = m_iNextMsgNo | MSGNO_PACKET_INORDER::mask;
|
||||
if (i == 0)
|
||||
s->m_iMsgNoBitset |= PacketBoundaryBits(PB_FIRST);
|
||||
if (i == iNumBlocks - 1)
|
||||
s->m_iMsgNoBitset |= PacketBoundaryBits(PB_LAST);
|
||||
// NOTE: PB_FIRST | PB_LAST == PB_SOLO.
|
||||
// none of PB_FIRST & PB_LAST == PB_SUBSEQUENT.
|
||||
|
||||
s->m_iLength = pktlen;
|
||||
s->m_iTTL = SRT_MSGTTL_INF;
|
||||
s = s->m_pNext;
|
||||
|
||||
total += pktlen;
|
||||
}
|
||||
m_pLastBlock = s;
|
||||
|
||||
enterCS(m_BufLock);
|
||||
m_iCount += iNumBlocks;
|
||||
m_iBytesCount += total;
|
||||
|
||||
leaveCS(m_BufLock);
|
||||
|
||||
m_iNextMsgNo++;
|
||||
if (m_iNextMsgNo == int32_t(MSGNO_SEQ::mask))
|
||||
m_iNextMsgNo = 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int CSndBuffer::readData(CPacket& w_packet, steady_clock::time_point& w_srctime, int kflgs, int& w_seqnoinc)
|
||||
{
|
||||
int readlen = 0;
|
||||
w_seqnoinc = 0;
|
||||
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
while (m_pCurrBlock != m_pLastBlock)
|
||||
{
|
||||
// Make the packet REFLECT the data stored in the buffer.
|
||||
w_packet.m_pcData = m_pCurrBlock->m_pcData;
|
||||
readlen = m_pCurrBlock->m_iLength;
|
||||
w_packet.setLength(readlen, m_iBlockLen);
|
||||
w_packet.m_iSeqNo = m_pCurrBlock->m_iSeqNo;
|
||||
|
||||
// 1. On submission (addBuffer), the KK flag is set to EK_NOENC (0).
|
||||
// 2. The readData() is called to get the original (unique) payload not ever sent yet.
|
||||
// The payload must be encrypted for the first time if the encryption
|
||||
// is enabled (arg kflgs != EK_NOENC). The KK encryption flag of the data packet
|
||||
// header must be set and remembered accordingly (see EncryptionKeySpec).
|
||||
// 3. The next time this packet is read (only for retransmission), the payload is already
|
||||
// encrypted, and the proper flag value is already stored.
|
||||
|
||||
// TODO: Alternatively, encryption could happen before the packet is submitted to the buffer
|
||||
// (before the addBuffer() call), and corresponding flags could be set accordingly.
|
||||
// This may also put an encryption burden on the application thread, rather than the sending thread,
|
||||
// which could be more efficient. Note that packet sequence number must be properly set in that case,
|
||||
// as it is used as a counter for the AES encryption.
|
||||
if (kflgs == -1)
|
||||
{
|
||||
HLOGC(bslog.Debug, log << CONID() << " CSndBuffer: ERROR: encryption required and not possible. NOT SENDING.");
|
||||
readlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurrBlock->m_iMsgNoBitset |= MSGNO_ENCKEYSPEC::wrap(kflgs);
|
||||
}
|
||||
|
||||
Block* p = m_pCurrBlock;
|
||||
w_packet.m_iMsgNo = m_pCurrBlock->m_iMsgNoBitset;
|
||||
w_srctime = m_pCurrBlock->m_tsOriginTime;
|
||||
m_pCurrBlock = m_pCurrBlock->m_pNext;
|
||||
|
||||
if ((p->m_iTTL >= 0) && (count_milliseconds(steady_clock::now() - w_srctime) > p->m_iTTL))
|
||||
{
|
||||
LOGC(bslog.Warn, log << CONID() << "CSndBuffer: skipping packet %" << p->m_iSeqNo << " #" << p->getMsgSeq() << " with TTL=" << p->m_iTTL);
|
||||
// Skip this packet due to TTL expiry.
|
||||
readlen = 0;
|
||||
++w_seqnoinc;
|
||||
continue;
|
||||
}
|
||||
|
||||
HLOGC(bslog.Debug, log << CONID() << "CSndBuffer: extracting packet size=" << readlen << " to send");
|
||||
break;
|
||||
}
|
||||
|
||||
return readlen;
|
||||
}
|
||||
|
||||
CSndBuffer::time_point CSndBuffer::peekNextOriginal() const
|
||||
{
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
if (m_pCurrBlock == m_pLastBlock)
|
||||
return time_point();
|
||||
|
||||
return m_pCurrBlock->m_tsOriginTime;
|
||||
}
|
||||
|
||||
int32_t CSndBuffer::getMsgNoAt(const int offset)
|
||||
{
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
|
||||
Block* p = m_pFirstBlock;
|
||||
|
||||
if (p)
|
||||
{
|
||||
HLOGC(bslog.Debug,
|
||||
log << "CSndBuffer::getMsgNoAt: FIRST MSG: size=" << p->m_iLength << " %" << p->m_iSeqNo << " #"
|
||||
<< p->getMsgSeq() << " !" << BufferStamp(p->m_pcData, p->m_iLength));
|
||||
}
|
||||
|
||||
if (offset >= m_iCount)
|
||||
{
|
||||
// Prevent accessing the last "marker" block
|
||||
LOGC(bslog.Error,
|
||||
log << "CSndBuffer::getMsgNoAt: IPE: offset=" << offset << " not found, max offset=" << m_iCount);
|
||||
return SRT_MSGNO_CONTROL;
|
||||
}
|
||||
|
||||
// XXX Suboptimal procedure to keep the blocks identifiable
|
||||
// by sequence number. Consider using some circular buffer.
|
||||
int i;
|
||||
Block* ee SRT_ATR_UNUSED = 0;
|
||||
for (i = 0; i < offset && p; ++i)
|
||||
{
|
||||
ee = p;
|
||||
p = p->m_pNext;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
LOGC(bslog.Error,
|
||||
log << "CSndBuffer::getMsgNoAt: IPE: offset=" << offset << " not found, stopped at " << i << " with #"
|
||||
<< (ee ? ee->getMsgSeq() : SRT_MSGNO_NONE));
|
||||
return SRT_MSGNO_CONTROL;
|
||||
}
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "CSndBuffer::getMsgNoAt: offset=" << offset << " found, size=" << p->m_iLength << " %" << p->m_iSeqNo
|
||||
<< " #" << p->getMsgSeq() << " !" << BufferStamp(p->m_pcData, p->m_iLength));
|
||||
|
||||
return p->getMsgSeq();
|
||||
}
|
||||
|
||||
int CSndBuffer::readData(const int offset, CPacket& w_packet, steady_clock::time_point& w_srctime, int& w_msglen)
|
||||
{
|
||||
int32_t& msgno_bitset = w_packet.m_iMsgNo;
|
||||
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
|
||||
Block* p = m_pFirstBlock;
|
||||
|
||||
// XXX Suboptimal procedure to keep the blocks identifiable
|
||||
// by sequence number. Consider using some circular buffer.
|
||||
for (int i = 0; i < offset && p != m_pLastBlock; ++i)
|
||||
{
|
||||
p = p->m_pNext;
|
||||
}
|
||||
if (p == m_pLastBlock)
|
||||
{
|
||||
LOGC(qslog.Error, log << "CSndBuffer::readData: offset " << offset << " too large!");
|
||||
return 0;
|
||||
}
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
const int32_t first_seq = p->m_iSeqNo;
|
||||
int32_t last_seq = p->m_iSeqNo;
|
||||
#endif
|
||||
|
||||
// Check if the block that is the next candidate to send (m_pCurrBlock pointing) is stale.
|
||||
|
||||
// If so, then inform the caller that it should first take care of the whole
|
||||
// message (all blocks with that message id). Shift the m_pCurrBlock pointer
|
||||
// to the position past the last of them. Then return -1 and set the
|
||||
// msgno_bitset return reference to the message id that should be dropped as
|
||||
// a whole.
|
||||
|
||||
// After taking care of that, the caller should immediately call this function again,
|
||||
// this time possibly in order to find the real data to be sent.
|
||||
|
||||
// if found block is stale
|
||||
// (This is for messages that have declared TTL - messages that fail to be sent
|
||||
// before the TTL defined time comes, will be dropped).
|
||||
|
||||
if ((p->m_iTTL >= 0) && (count_milliseconds(steady_clock::now() - p->m_tsOriginTime) > p->m_iTTL))
|
||||
{
|
||||
int32_t msgno = p->getMsgSeq();
|
||||
w_msglen = 1;
|
||||
p = p->m_pNext;
|
||||
bool move = false;
|
||||
while (p != m_pLastBlock && msgno == p->getMsgSeq())
|
||||
{
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
last_seq = p->m_iSeqNo;
|
||||
#endif
|
||||
if (p == m_pCurrBlock)
|
||||
move = true;
|
||||
p = p->m_pNext;
|
||||
if (move)
|
||||
m_pCurrBlock = p;
|
||||
w_msglen++;
|
||||
}
|
||||
|
||||
HLOGC(qslog.Debug,
|
||||
log << "CSndBuffer::readData: due to TTL exceeded, SEQ " << first_seq << " - " << last_seq << ", "
|
||||
<< w_msglen << " packets to drop, msgno=" << msgno);
|
||||
|
||||
// If readData returns -1, then msgno_bitset is understood as a Message ID to drop.
|
||||
// This means that in this case it should be written by the message sequence value only
|
||||
// (not the whole 4-byte bitset written at PH_MSGNO).
|
||||
msgno_bitset = msgno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
w_packet.m_pcData = p->m_pcData;
|
||||
const int readlen = p->m_iLength;
|
||||
w_packet.setLength(readlen, m_iBlockLen);
|
||||
|
||||
// XXX Here the value predicted to be applied to PH_MSGNO field is extracted.
|
||||
// As this function is predicted to extract the data to send as a rexmited packet,
|
||||
// the packet must be in the form ready to send - so, in case of encryption,
|
||||
// encrypted, and with all ENC flags already set. So, the first call to send
|
||||
// the packet originally (the other overload of this function) must set these
|
||||
// flags.
|
||||
w_packet.m_iMsgNo = p->m_iMsgNoBitset;
|
||||
w_srctime = p->m_tsOriginTime;
|
||||
|
||||
// This function is called when packet retransmission is triggered.
|
||||
// Therefore we are setting the rexmit time.
|
||||
p->m_tsRexmitTime = steady_clock::now();
|
||||
|
||||
HLOGC(qslog.Debug,
|
||||
log << CONID() << "CSndBuffer: getting packet %" << p->m_iSeqNo << " as per %" << w_packet.m_iSeqNo
|
||||
<< " size=" << readlen << " to send [REXMIT]");
|
||||
|
||||
return readlen;
|
||||
}
|
||||
|
||||
sync::steady_clock::time_point CSndBuffer::getPacketRexmitTime(const int offset)
|
||||
{
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
const Block* p = m_pFirstBlock;
|
||||
|
||||
// XXX Suboptimal procedure to keep the blocks identifiable
|
||||
// by sequence number. Consider using some circular buffer.
|
||||
for (int i = 0; i < offset; ++i)
|
||||
{
|
||||
SRT_ASSERT(p);
|
||||
p = p->m_pNext;
|
||||
}
|
||||
|
||||
SRT_ASSERT(p);
|
||||
return p->m_tsRexmitTime;
|
||||
}
|
||||
|
||||
void CSndBuffer::ackData(int offset)
|
||||
{
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
|
||||
bool move = false;
|
||||
for (int i = 0; i < offset; ++i)
|
||||
{
|
||||
m_iBytesCount -= m_pFirstBlock->m_iLength;
|
||||
if (m_pFirstBlock == m_pCurrBlock)
|
||||
move = true;
|
||||
m_pFirstBlock = m_pFirstBlock->m_pNext;
|
||||
}
|
||||
if (move)
|
||||
m_pCurrBlock = m_pFirstBlock;
|
||||
|
||||
m_iCount -= offset;
|
||||
|
||||
updAvgBufSize(steady_clock::now());
|
||||
}
|
||||
|
||||
int CSndBuffer::getCurrBufSize() const
|
||||
{
|
||||
return m_iCount;
|
||||
}
|
||||
|
||||
int CSndBuffer::getMaxPacketLen() const
|
||||
{
|
||||
return m_iBlockLen - m_iAuthTagSize;
|
||||
}
|
||||
|
||||
int CSndBuffer::countNumPacketsRequired(int iPldLen) const
|
||||
{
|
||||
const int iPktLen = getMaxPacketLen();
|
||||
return countNumPacketsRequired(iPldLen, iPktLen);
|
||||
}
|
||||
|
||||
int CSndBuffer::countNumPacketsRequired(int iPldLen, int iPktLen) const
|
||||
{
|
||||
return (iPldLen + iPktLen - 1) / iPktLen;
|
||||
}
|
||||
|
||||
namespace {
|
||||
int round_val(double val)
|
||||
{
|
||||
return static_cast<int>(round(val));
|
||||
}
|
||||
}
|
||||
|
||||
int CSndBuffer::getAvgBufSize(int& w_bytes, int& w_tsp)
|
||||
{
|
||||
ScopedLock bufferguard(m_BufLock); /* Consistency of pkts vs. bytes vs. spantime */
|
||||
|
||||
/* update stats in case there was no add/ack activity lately */
|
||||
updAvgBufSize(steady_clock::now());
|
||||
|
||||
// Average number of packets and timespan could be small,
|
||||
// so rounding is beneficial, while for the number of
|
||||
// bytes in the buffer is a higher value, so rounding can be omitted,
|
||||
// but probably better to round all three values.
|
||||
w_bytes = round_val(m_mavg.bytes());
|
||||
w_tsp = round_val(m_mavg.timespan_ms());
|
||||
return round_val(m_mavg.pkts());
|
||||
}
|
||||
|
||||
void CSndBuffer::updAvgBufSize(const steady_clock::time_point& now)
|
||||
{
|
||||
if (!m_mavg.isTimeToUpdate(now))
|
||||
return;
|
||||
|
||||
int bytes = 0;
|
||||
int timespan_ms = 0;
|
||||
const int pkts = getCurrBufSize((bytes), (timespan_ms));
|
||||
m_mavg.update(now, pkts, bytes, timespan_ms);
|
||||
}
|
||||
|
||||
int CSndBuffer::getCurrBufSize(int& w_bytes, int& w_timespan) const
|
||||
{
|
||||
w_bytes = m_iBytesCount;
|
||||
/*
|
||||
* Timespan can be less then 1000 us (1 ms) if few packets.
|
||||
* Also, if there is only one pkt in buffer, the time difference will be 0.
|
||||
* Therefore, always add 1 ms if not empty.
|
||||
*/
|
||||
w_timespan = 0 < m_iCount ? (int) count_milliseconds(m_tsLastOriginTime - m_pFirstBlock->m_tsOriginTime) + 1 : 0;
|
||||
|
||||
return m_iCount;
|
||||
}
|
||||
|
||||
CSndBuffer::duration CSndBuffer::getBufferingDelay(const time_point& tnow) const
|
||||
{
|
||||
ScopedLock lck(m_BufLock);
|
||||
SRT_ASSERT(m_pFirstBlock);
|
||||
if (m_iCount == 0)
|
||||
return duration(0);
|
||||
|
||||
return tnow - m_pFirstBlock->m_tsOriginTime;
|
||||
}
|
||||
|
||||
int CSndBuffer::dropLateData(int& w_bytes, int32_t& w_first_msgno, const steady_clock::time_point& too_late_time)
|
||||
{
|
||||
int dpkts = 0;
|
||||
int dbytes = 0;
|
||||
bool move = false;
|
||||
int32_t msgno = 0;
|
||||
|
||||
ScopedLock bufferguard(m_BufLock);
|
||||
for (int i = 0; i < m_iCount && m_pFirstBlock->m_tsOriginTime < too_late_time; ++i)
|
||||
{
|
||||
dpkts++;
|
||||
dbytes += m_pFirstBlock->m_iLength;
|
||||
msgno = m_pFirstBlock->getMsgSeq();
|
||||
|
||||
if (m_pFirstBlock == m_pCurrBlock)
|
||||
move = true;
|
||||
m_pFirstBlock = m_pFirstBlock->m_pNext;
|
||||
}
|
||||
|
||||
if (move)
|
||||
{
|
||||
m_pCurrBlock = m_pFirstBlock;
|
||||
}
|
||||
m_iCount -= dpkts;
|
||||
|
||||
m_iBytesCount -= dbytes;
|
||||
w_bytes = dbytes;
|
||||
|
||||
// We report the increased number towards the last ever seen
|
||||
// by the loop, as this last one is the last received. So remained
|
||||
// (even if "should remain") is the first after the last removed one.
|
||||
w_first_msgno = ++MsgNo(msgno);
|
||||
|
||||
updAvgBufSize(steady_clock::now());
|
||||
|
||||
return (dpkts);
|
||||
}
|
||||
|
||||
void CSndBuffer::increase()
|
||||
{
|
||||
int unitsize = m_pBuffer->m_iSize;
|
||||
|
||||
// new physical buffer
|
||||
Buffer* nbuf = NULL;
|
||||
try
|
||||
{
|
||||
nbuf = new Buffer;
|
||||
nbuf->m_pcData = new char[unitsize * m_iBlockLen];
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete nbuf;
|
||||
throw CUDTException(MJ_SYSTEMRES, MN_MEMORY, 0);
|
||||
}
|
||||
nbuf->m_iSize = unitsize;
|
||||
nbuf->m_pNext = NULL;
|
||||
|
||||
// insert the buffer at the end of the buffer list
|
||||
Buffer* p = m_pBuffer;
|
||||
while (p->m_pNext != NULL)
|
||||
p = p->m_pNext;
|
||||
p->m_pNext = nbuf;
|
||||
|
||||
// new packet blocks
|
||||
Block* nblk = NULL;
|
||||
try
|
||||
{
|
||||
nblk = new Block;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete nblk;
|
||||
throw CUDTException(MJ_SYSTEMRES, MN_MEMORY, 0);
|
||||
}
|
||||
Block* pb = nblk;
|
||||
for (int i = 1; i < unitsize; ++i)
|
||||
{
|
||||
pb->m_pNext = new Block;
|
||||
pb = pb->m_pNext;
|
||||
}
|
||||
|
||||
// insert the new blocks onto the existing one
|
||||
pb->m_pNext = m_pLastBlock->m_pNext;
|
||||
m_pLastBlock->m_pNext = nblk;
|
||||
|
||||
pb = nblk;
|
||||
char* pc = nbuf->m_pcData;
|
||||
for (int i = 0; i < unitsize; ++i)
|
||||
{
|
||||
pb->m_pcData = pc;
|
||||
pb = pb->m_pNext;
|
||||
pc += m_iBlockLen;
|
||||
}
|
||||
|
||||
m_iSize += unitsize;
|
||||
|
||||
HLOGC(bslog.Debug,
|
||||
log << "CSndBuffer: BUFFER FULL - adding " << (unitsize * m_iBlockLen) << " bytes spread to " << unitsize
|
||||
<< " blocks"
|
||||
<< " (total size: " << m_iSize << " bytes)");
|
||||
}
|
||||
|
||||
} // namespace srt
|
259
trunk/3rdparty/srt-1-fit/srtcore/buffer_snd.h
vendored
Normal file
259
trunk/3rdparty/srt-1-fit/srtcore/buffer_snd.h
vendored
Normal file
|
@ -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
|
275
trunk/3rdparty/srt-1-fit/srtcore/buffer_tools.cpp
vendored
Normal file
275
trunk/3rdparty/srt-1-fit/srtcore/buffer_tools.cpp
vendored
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* 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 03/12/2011
|
||||
modified by
|
||||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "platform_sys.h"
|
||||
#include "buffer_tools.h"
|
||||
#include "packet.h"
|
||||
#include "logger_defs.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace srt {
|
||||
|
||||
using namespace std;
|
||||
using namespace srt_logging;
|
||||
using namespace sync;
|
||||
|
||||
// You can change this value at build config by using "ENFORCE" options.
|
||||
#if !defined(SRT_MAVG_SAMPLING_RATE)
|
||||
#define SRT_MAVG_SAMPLING_RATE 40
|
||||
#endif
|
||||
|
||||
bool AvgBufSize::isTimeToUpdate(const time_point& now) const
|
||||
{
|
||||
const int usMAvgBasePeriod = 1000000; // 1s in microseconds
|
||||
const int us2ms = 1000;
|
||||
const int msMAvgPeriod = (usMAvgBasePeriod / SRT_MAVG_SAMPLING_RATE) / us2ms;
|
||||
const uint64_t elapsed_ms = count_milliseconds(now - m_tsLastSamplingTime); // ms since last sampling
|
||||
return (elapsed_ms >= msMAvgPeriod);
|
||||
}
|
||||
|
||||
void AvgBufSize::update(const steady_clock::time_point& now, int pkts, int bytes, int timespan_ms)
|
||||
{
|
||||
const uint64_t elapsed_ms = count_milliseconds(now - m_tsLastSamplingTime); // ms since last sampling
|
||||
m_tsLastSamplingTime = now;
|
||||
const uint64_t one_second_in_ms = 1000;
|
||||
if (elapsed_ms > one_second_in_ms)
|
||||
{
|
||||
// No sampling in last 1 sec, initialize average
|
||||
m_dCountMAvg = pkts;
|
||||
m_dBytesCountMAvg = bytes;
|
||||
m_dTimespanMAvg = timespan_ms;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// weight last average value between -1 sec and last sampling time (LST)
|
||||
// and new value between last sampling time and now
|
||||
// |elapsed_ms|
|
||||
// +----------------------------------+-------+
|
||||
// -1 LST 0(now)
|
||||
//
|
||||
m_dCountMAvg = avg_iir_w<1000, double>(m_dCountMAvg, pkts, elapsed_ms);
|
||||
m_dBytesCountMAvg = avg_iir_w<1000, double>(m_dBytesCountMAvg, bytes, elapsed_ms);
|
||||
m_dTimespanMAvg = avg_iir_w<1000, double>(m_dTimespanMAvg, timespan_ms, elapsed_ms);
|
||||
}
|
||||
|
||||
CRateEstimator::CRateEstimator()
|
||||
: m_iInRatePktsCount(0)
|
||||
, m_iInRateBytesCount(0)
|
||||
, m_InRatePeriod(INPUTRATE_FAST_START_US) // 0.5 sec (fast start)
|
||||
, m_iInRateBps(INPUTRATE_INITIAL_BYTESPS)
|
||||
{}
|
||||
|
||||
void CRateEstimator::setInputRateSmpPeriod(int period)
|
||||
{
|
||||
m_InRatePeriod = (uint64_t)period; //(usec) 0=no input rate calculation
|
||||
}
|
||||
|
||||
void CRateEstimator::updateInputRate(const time_point& time, int pkts, int bytes)
|
||||
{
|
||||
// no input rate calculation
|
||||
if (m_InRatePeriod == 0)
|
||||
return;
|
||||
|
||||
if (is_zero(m_tsInRateStartTime))
|
||||
{
|
||||
m_tsInRateStartTime = time;
|
||||
return;
|
||||
}
|
||||
else if (time < m_tsInRateStartTime)
|
||||
{
|
||||
// Old packets are being submitted for estimation, e.g. during the backup link activation.
|
||||
return;
|
||||
}
|
||||
|
||||
m_iInRatePktsCount += pkts;
|
||||
m_iInRateBytesCount += bytes;
|
||||
|
||||
// Trigger early update in fast start mode
|
||||
const bool early_update = (m_InRatePeriod < INPUTRATE_RUNNING_US) && (m_iInRatePktsCount > INPUTRATE_MAX_PACKETS);
|
||||
|
||||
const uint64_t period_us = count_microseconds(time - m_tsInRateStartTime);
|
||||
if (!early_update && period_us <= m_InRatePeriod)
|
||||
return;
|
||||
|
||||
// Required Byte/sec rate (payload + headers)
|
||||
m_iInRateBytesCount += (m_iInRatePktsCount * CPacket::SRT_DATA_HDR_SIZE);
|
||||
m_iInRateBps = (int)(((int64_t)m_iInRateBytesCount * 1000000) / period_us);
|
||||
HLOGC(bslog.Debug,
|
||||
log << "updateInputRate: pkts:" << m_iInRateBytesCount << " bytes:" << m_iInRatePktsCount
|
||||
<< " rate=" << (m_iInRateBps * 8) / 1000 << "kbps interval=" << period_us);
|
||||
m_iInRatePktsCount = 0;
|
||||
m_iInRateBytesCount = 0;
|
||||
m_tsInRateStartTime = time;
|
||||
|
||||
setInputRateSmpPeriod(INPUTRATE_RUNNING_US);
|
||||
}
|
||||
|
||||
CSndRateEstimator::CSndRateEstimator(const time_point& tsNow)
|
||||
: m_tsFirstSampleTime(tsNow)
|
||||
, m_iFirstSampleIdx(0)
|
||||
, m_iCurSampleIdx(0)
|
||||
, m_iRateBps(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSndRateEstimator::addSample(const time_point& ts, int pkts, size_t bytes)
|
||||
{
|
||||
const int iSampleDeltaIdx = (int) count_milliseconds(ts - m_tsFirstSampleTime) / SAMPLE_DURATION_MS;
|
||||
const int delta = NUM_PERIODS - iSampleDeltaIdx;
|
||||
|
||||
// TODO: -delta <= NUM_PERIODS, then just reset the state on the estimator.
|
||||
|
||||
if (iSampleDeltaIdx >= 2 * NUM_PERIODS)
|
||||
{
|
||||
// Just reset the estimator and start like if new.
|
||||
for (int i = 0; i < NUM_PERIODS; ++i)
|
||||
{
|
||||
const int idx = incSampleIdx(m_iFirstSampleIdx, i);
|
||||
m_Samples[idx].reset();
|
||||
|
||||
if (idx == m_iCurSampleIdx)
|
||||
break;
|
||||
}
|
||||
|
||||
m_iFirstSampleIdx = 0;
|
||||
m_iCurSampleIdx = 0;
|
||||
m_iRateBps = 0;
|
||||
m_tsFirstSampleTime += milliseconds_from(iSampleDeltaIdx * SAMPLE_DURATION_MS);
|
||||
}
|
||||
else if (iSampleDeltaIdx > NUM_PERIODS)
|
||||
{
|
||||
// In run-time a constant flow of samples is expected. Once all periods are filled (after 1 second of sampling),
|
||||
// the iSampleDeltaIdx should be either (NUM_PERIODS - 1),
|
||||
// or NUM_PERIODS. In the later case it means the start of a new sampling period.
|
||||
int d = delta;
|
||||
while (d < 0)
|
||||
{
|
||||
m_Samples[m_iFirstSampleIdx].reset();
|
||||
m_iFirstSampleIdx = incSampleIdx(m_iFirstSampleIdx);
|
||||
m_tsFirstSampleTime += milliseconds_from(SAMPLE_DURATION_MS);
|
||||
m_iCurSampleIdx = incSampleIdx(m_iCurSampleIdx);
|
||||
++d;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the new sample period has started.
|
||||
const int iNewDeltaIdx = (int) count_milliseconds(ts - m_tsFirstSampleTime) / SAMPLE_DURATION_MS;
|
||||
if (incSampleIdx(m_iFirstSampleIdx, iNewDeltaIdx) != m_iCurSampleIdx)
|
||||
{
|
||||
// Now there should be some periods (at most last NUM_PERIODS) ready to be summed,
|
||||
// rate estimation updated, after which all the new entry should be added.
|
||||
Sample sum;
|
||||
int iNumPeriods = 0;
|
||||
bool bMetNonEmpty = false;
|
||||
for (int i = 0; i < NUM_PERIODS; ++i)
|
||||
{
|
||||
const int idx = incSampleIdx(m_iFirstSampleIdx, i);
|
||||
const Sample& s = m_Samples[idx];
|
||||
sum += s;
|
||||
if (bMetNonEmpty || !s.empty())
|
||||
{
|
||||
++iNumPeriods;
|
||||
bMetNonEmpty = true;
|
||||
}
|
||||
|
||||
if (idx == m_iCurSampleIdx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (iNumPeriods == 0)
|
||||
{
|
||||
m_iRateBps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iRateBps = sum.m_iBytesCount * 1000 / (iNumPeriods * SAMPLE_DURATION_MS);
|
||||
}
|
||||
|
||||
HLOGC(bslog.Note,
|
||||
log << "CSndRateEstimator: new rate estimation :" << (m_iRateBps * 8) / 1000 << " kbps. Based on "
|
||||
<< iNumPeriods << " periods, " << sum.m_iPktsCount << " packets, " << sum.m_iBytesCount << " bytes.");
|
||||
|
||||
// Shift one sampling period to start collecting the new one.
|
||||
m_iCurSampleIdx = incSampleIdx(m_iCurSampleIdx);
|
||||
m_Samples[m_iCurSampleIdx].reset();
|
||||
|
||||
// If all NUM_SAMPLES are recorded, the first position has to be shifted as well.
|
||||
if (delta <= 0)
|
||||
{
|
||||
m_iFirstSampleIdx = incSampleIdx(m_iFirstSampleIdx);
|
||||
m_tsFirstSampleTime += milliseconds_from(SAMPLE_DURATION_MS);
|
||||
}
|
||||
}
|
||||
|
||||
m_Samples[m_iCurSampleIdx].m_iBytesCount += bytes;
|
||||
m_Samples[m_iCurSampleIdx].m_iPktsCount += pkts;
|
||||
}
|
||||
|
||||
int CSndRateEstimator::getCurrentRate() const
|
||||
{
|
||||
SRT_ASSERT(m_iCurSampleIdx >= 0 && m_iCurSampleIdx < NUM_PERIODS);
|
||||
return (int) avg_iir<16, unsigned long long>(m_iRateBps, m_Samples[m_iCurSampleIdx].m_iBytesCount * 1000 / SAMPLE_DURATION_MS);
|
||||
}
|
||||
|
||||
int CSndRateEstimator::incSampleIdx(int val, int inc) const
|
||||
{
|
||||
SRT_ASSERT(inc >= 0 && inc <= NUM_PERIODS);
|
||||
val += inc;
|
||||
while (val >= NUM_PERIODS)
|
||||
val -= NUM_PERIODS;
|
||||
return val;
|
||||
}
|
||||
|
||||
}
|
||||
|
201
trunk/3rdparty/srt-1-fit/srtcore/buffer_tools.h
vendored
Normal file
201
trunk/3rdparty/srt-1-fit/srtcore/buffer_tools.h
vendored
Normal file
|
@ -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
|
52
trunk/3rdparty/srt-1-fit/srtcore/cache.cpp
vendored
52
trunk/3rdparty/srt-1-fit/srtcore/cache.cpp
vendored
|
@ -38,10 +38,8 @@ written by
|
|||
Yunhong Gu, last updated 05/05/2009
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include "platform_sys.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "cache.h"
|
||||
|
@ -49,22 +47,22 @@ written by
|
|||
|
||||
using namespace std;
|
||||
|
||||
CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj)
|
||||
srt::CInfoBlock& srt::CInfoBlock::copyFrom(const CInfoBlock& obj)
|
||||
{
|
||||
std::copy(obj.m_piIP, obj.m_piIP + 4, m_piIP);
|
||||
m_iIPversion = obj.m_iIPversion;
|
||||
m_ullTimeStamp = obj.m_ullTimeStamp;
|
||||
m_iRTT = obj.m_iRTT;
|
||||
m_iBandwidth = obj.m_iBandwidth;
|
||||
m_iLossRate = obj.m_iLossRate;
|
||||
m_iIPversion = obj.m_iIPversion;
|
||||
m_ullTimeStamp = obj.m_ullTimeStamp;
|
||||
m_iSRTT = obj.m_iSRTT;
|
||||
m_iBandwidth = obj.m_iBandwidth;
|
||||
m_iLossRate = obj.m_iLossRate;
|
||||
m_iReorderDistance = obj.m_iReorderDistance;
|
||||
m_dInterval = obj.m_dInterval;
|
||||
m_dCWnd = obj.m_dCWnd;
|
||||
m_dInterval = obj.m_dInterval;
|
||||
m_dCWnd = obj.m_dCWnd;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CInfoBlock::operator==(const CInfoBlock& obj)
|
||||
bool srt::CInfoBlock::operator==(const CInfoBlock& obj) const
|
||||
{
|
||||
if (m_iIPversion != obj.m_iIPversion)
|
||||
return false;
|
||||
|
@ -81,24 +79,24 @@ bool CInfoBlock::operator==(const CInfoBlock& obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
CInfoBlock* CInfoBlock::clone()
|
||||
srt::CInfoBlock* srt::CInfoBlock::clone()
|
||||
{
|
||||
CInfoBlock* obj = new CInfoBlock;
|
||||
|
||||
std::copy(m_piIP, m_piIP + 4, obj->m_piIP);
|
||||
obj->m_iIPversion = m_iIPversion;
|
||||
obj->m_ullTimeStamp = m_ullTimeStamp;
|
||||
obj->m_iRTT = m_iRTT;
|
||||
obj->m_iBandwidth = m_iBandwidth;
|
||||
obj->m_iLossRate = m_iLossRate;
|
||||
obj->m_iIPversion = m_iIPversion;
|
||||
obj->m_ullTimeStamp = m_ullTimeStamp;
|
||||
obj->m_iSRTT = m_iSRTT;
|
||||
obj->m_iBandwidth = m_iBandwidth;
|
||||
obj->m_iLossRate = m_iLossRate;
|
||||
obj->m_iReorderDistance = m_iReorderDistance;
|
||||
obj->m_dInterval = m_dInterval;
|
||||
obj->m_dCWnd = m_dCWnd;
|
||||
obj->m_dInterval = m_dInterval;
|
||||
obj->m_dCWnd = m_dCWnd;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
int CInfoBlock::getKey()
|
||||
int srt::CInfoBlock::getKey()
|
||||
{
|
||||
if (m_iIPversion == AF_INET)
|
||||
return m_piIP[0];
|
||||
|
@ -106,15 +104,15 @@ int CInfoBlock::getKey()
|
|||
return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3];
|
||||
}
|
||||
|
||||
void CInfoBlock::convert(const sockaddr* addr, int ver, uint32_t ip[])
|
||||
void srt::CInfoBlock::convert(const sockaddr_any& addr, uint32_t aw_ip[4])
|
||||
{
|
||||
if (ver == AF_INET)
|
||||
if (addr.family() == AF_INET)
|
||||
{
|
||||
ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr;
|
||||
ip[1] = ip[2] = ip[3] = 0;
|
||||
aw_ip[0] = addr.sin.sin_addr.s_addr;
|
||||
aw_ip[1] = aw_ip[2] = aw_ip[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16);
|
||||
memcpy((aw_ip), addr.sin6.sin6_addr.s6_addr, sizeof addr.sin6.sin6_addr.s6_addr);
|
||||
}
|
||||
}
|
||||
|
|
55
trunk/3rdparty/srt-1-fit/srtcore/cache.h
vendored
55
trunk/3rdparty/srt-1-fit/srtcore/cache.h
vendored
|
@ -38,15 +38,19 @@ written by
|
|||
Yunhong Gu, last updated 01/27/2011
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_CACHE_H__
|
||||
#define __UDT_CACHE_H__
|
||||
#ifndef INC_SRT_CACHE_H
|
||||
#define INC_SRT_CACHE_H
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
#include "sync.h"
|
||||
#include "netinet_any.h"
|
||||
#include "udt.h"
|
||||
|
||||
namespace srt
|
||||
{
|
||||
|
||||
class CCacheItem
|
||||
{
|
||||
public:
|
||||
|
@ -82,13 +86,13 @@ public:
|
|||
m_iCurrSize(0)
|
||||
{
|
||||
m_vHashPtr.resize(m_iHashSize);
|
||||
CGuard::createMutex(m_Lock);
|
||||
// Exception: -> CUDTUnited ctor
|
||||
srt::sync::setupMutex(m_Lock, "Cache");
|
||||
}
|
||||
|
||||
~CCache()
|
||||
{
|
||||
clear();
|
||||
CGuard::releaseMutex(m_Lock);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -98,7 +102,7 @@ public:
|
|||
|
||||
int lookup(T* data)
|
||||
{
|
||||
CGuard cacheguard(m_Lock);
|
||||
srt::sync::ScopedLock cacheguard(m_Lock);
|
||||
|
||||
int key = data->getKey();
|
||||
if (key < 0)
|
||||
|
@ -126,7 +130,7 @@ public:
|
|||
|
||||
int update(T* data)
|
||||
{
|
||||
CGuard cacheguard(m_Lock);
|
||||
srt::sync::ScopedLock cacheguard(m_Lock);
|
||||
|
||||
int key = data->getKey();
|
||||
if (key < 0)
|
||||
|
@ -223,7 +227,7 @@ private:
|
|||
int m_iHashSize;
|
||||
int m_iCurrSize;
|
||||
|
||||
pthread_mutex_t m_Lock;
|
||||
srt::sync::Mutex m_Lock;
|
||||
|
||||
private:
|
||||
CCache(const CCache&);
|
||||
|
@ -234,23 +238,25 @@ private:
|
|||
class CInfoBlock
|
||||
{
|
||||
public:
|
||||
uint32_t m_piIP[4]; // IP address, machine read only, not human readable format
|
||||
int m_iIPversion; // IP version
|
||||
uint64_t m_ullTimeStamp; // last update time
|
||||
int m_iRTT; // RTT
|
||||
int m_iBandwidth; // estimated bandwidth
|
||||
int m_iLossRate; // average loss rate
|
||||
int m_iReorderDistance; // packet reordering distance
|
||||
double m_dInterval; // inter-packet time, congestion control
|
||||
double m_dCWnd; // congestion window size, congestion control
|
||||
uint32_t m_piIP[4]; // IP address, machine read only, not human readable format.
|
||||
int m_iIPversion; // Address family: AF_INET or AF_INET6.
|
||||
uint64_t m_ullTimeStamp; // Last update time.
|
||||
int m_iSRTT; // Smoothed RTT.
|
||||
int m_iBandwidth; // Estimated link bandwidth.
|
||||
int m_iLossRate; // Average loss rate.
|
||||
int m_iReorderDistance; // Packet reordering distance.
|
||||
double m_dInterval; // Inter-packet time (Congestion Control).
|
||||
double m_dCWnd; // Congestion window size (Congestion Control).
|
||||
|
||||
public:
|
||||
virtual ~CInfoBlock() {}
|
||||
virtual CInfoBlock& operator=(const CInfoBlock& obj);
|
||||
virtual bool operator==(const CInfoBlock& obj);
|
||||
virtual CInfoBlock* clone();
|
||||
virtual int getKey();
|
||||
virtual void release() {}
|
||||
CInfoBlock() {} // NOTE: leaves uninitialized
|
||||
CInfoBlock& copyFrom(const CInfoBlock& obj);
|
||||
CInfoBlock(const CInfoBlock& src) { copyFrom(src); }
|
||||
CInfoBlock& operator=(const CInfoBlock& src) { return copyFrom(src); }
|
||||
bool operator==(const CInfoBlock& obj) const;
|
||||
CInfoBlock* clone();
|
||||
int getKey();
|
||||
void release() {}
|
||||
|
||||
public:
|
||||
|
||||
|
@ -259,8 +265,9 @@ public:
|
|||
/// @param [in] ver IP version
|
||||
/// @param [out] ip the result machine readable IP address in integer array
|
||||
|
||||
static void convert(const sockaddr* addr, int ver, uint32_t ip[]);
|
||||
static void convert(const sockaddr_any& addr, uint32_t ip[4]);
|
||||
};
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif
|
||||
|
|
1193
trunk/3rdparty/srt-1-fit/srtcore/channel.cpp
vendored
1193
trunk/3rdparty/srt-1-fit/srtcore/channel.cpp
vendored
File diff suppressed because it is too large
Load diff
287
trunk/3rdparty/srt-1-fit/srtcore/channel.h
vendored
287
trunk/3rdparty/srt-1-fit/srtcore/channel.h
vendored
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -50,138 +50,249 @@ modified by
|
|||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_CHANNEL_H__
|
||||
#define __UDT_CHANNEL_H__
|
||||
|
||||
#ifndef INC_SRT_CHANNEL_H
|
||||
#define INC_SRT_CHANNEL_H
|
||||
|
||||
#include "platform_sys.h"
|
||||
#include "udt.h"
|
||||
#include "packet.h"
|
||||
#include "socketconfig.h"
|
||||
#include "netinet_any.h"
|
||||
|
||||
namespace srt
|
||||
{
|
||||
|
||||
class CChannel
|
||||
{
|
||||
void createSocket(int family);
|
||||
|
||||
public:
|
||||
// XXX There's currently no way to access the socket ID set for
|
||||
// whatever the channel 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 ""; }
|
||||
|
||||
// XXX There's currently no way to access the socket ID set for
|
||||
// whatever the channel 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 ""; }
|
||||
CChannel();
|
||||
~CChannel();
|
||||
|
||||
CChannel();
|
||||
CChannel(int version);
|
||||
~CChannel();
|
||||
/// Open a UDP channel.
|
||||
/// @param [in] addr The local address that UDP will use.
|
||||
|
||||
/// Open a UDP channel.
|
||||
/// @param [in] addr The local address that UDP will use.
|
||||
void open(const sockaddr_any& addr);
|
||||
|
||||
void open(const sockaddr* addr = NULL);
|
||||
void open(int family);
|
||||
|
||||
/// Open a UDP channel based on an existing UDP socket.
|
||||
/// @param [in] udpsock UDP socket descriptor.
|
||||
/// Open a UDP channel based on an existing UDP socket.
|
||||
/// @param [in] udpsock UDP socket descriptor.
|
||||
|
||||
void attach(UDPSOCKET udpsock);
|
||||
void attach(UDPSOCKET udpsock, const sockaddr_any& adr);
|
||||
|
||||
/// Disconnect and close the UDP entity.
|
||||
/// Disconnect and close the UDP entity.
|
||||
|
||||
void close() const;
|
||||
void close() const;
|
||||
|
||||
/// Get the UDP sending buffer size.
|
||||
/// @return Current UDP sending buffer size.
|
||||
/// Get the UDP sending buffer size.
|
||||
/// @return Current UDP sending buffer size.
|
||||
|
||||
int getSndBufSize();
|
||||
int getSndBufSize();
|
||||
|
||||
/// Get the UDP receiving buffer size.
|
||||
/// @return Current UDP receiving buffer size.
|
||||
/// Get the UDP receiving buffer size.
|
||||
/// @return Current UDP receiving buffer size.
|
||||
|
||||
int getRcvBufSize();
|
||||
int getRcvBufSize();
|
||||
|
||||
/// Set the UDP sending buffer size.
|
||||
/// @param [in] size expected UDP sending buffer size.
|
||||
/// Query the socket address that the channel is using.
|
||||
/// @param [out] addr pointer to store the returned socket address.
|
||||
|
||||
void setSndBufSize(int size);
|
||||
void getSockAddr(sockaddr_any& addr) const;
|
||||
|
||||
/// Set the UDP receiving buffer size.
|
||||
/// @param [in] size expected UDP receiving buffer size.
|
||||
/// Query the peer side socket address that the channel is connect to.
|
||||
/// @param [out] addr pointer to store the returned socket address.
|
||||
|
||||
void setRcvBufSize(int size);
|
||||
void getPeerAddr(sockaddr_any& addr) const;
|
||||
|
||||
/// Set the IPV6ONLY option.
|
||||
/// @param [in] IPV6ONLY value.
|
||||
/// 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.
|
||||
|
||||
void setIpV6Only(int ipV6Only);
|
||||
int sendto(const sockaddr_any& addr, srt::CPacket& packet, const sockaddr_any& src) const;
|
||||
|
||||
/// Query the socket address that the channel is using.
|
||||
/// @param [out] addr pointer to store the returned socket address.
|
||||
/// Receive a packet from the channel and record the source address.
|
||||
/// @param [in] addr pointer to the source address.
|
||||
/// @param [in] packet reference to a CPacket entity.
|
||||
/// @return Actual size of data received.
|
||||
|
||||
void getSockAddr(sockaddr* addr) const;
|
||||
EReadStatus recvfrom(sockaddr_any& addr, srt::CPacket& packet) const;
|
||||
|
||||
/// Query the peer side socket address that the channel is connect to.
|
||||
/// @param [out] addr pointer to store the returned socket address.
|
||||
void setConfig(const CSrtMuxerConfig& config);
|
||||
|
||||
void getPeerAddr(sockaddr* addr) const;
|
||||
void getSocketOption(int level, int sockoptname, char* pw_dataptr, socklen_t& w_len, int& w_status);
|
||||
|
||||
/// Send a packet to the given address.
|
||||
/// @param [in] addr pointer to the destination address.
|
||||
/// @param [in] packet reference to a CPacket entity.
|
||||
/// @return Actual size of data sent.
|
||||
template<class Type>
|
||||
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;
|
||||
|
||||
int sendto(const sockaddr* addr, CPacket& packet) const;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Receive a packet from the channel and record the source address.
|
||||
/// @param [in] addr pointer to the source address.
|
||||
/// @param [in] packet reference to a CPacket entity.
|
||||
/// @return Actual size of data received.
|
||||
/// Get the IP TTL.
|
||||
/// @param [in] ttl IP Time To Live.
|
||||
/// @return TTL.
|
||||
|
||||
EReadStatus recvfrom(sockaddr* addr, CPacket& packet) const;
|
||||
int getIpTTL() const;
|
||||
|
||||
#ifdef SRT_ENABLE_IPOPTS
|
||||
/// Set the IP TTL.
|
||||
/// @param [in] ttl IP Time To Live.
|
||||
/// @return none.
|
||||
/// Get the IP Type of Service.
|
||||
/// @return ToS.
|
||||
|
||||
void setIpTTL(int ttl);
|
||||
int getIpToS() const;
|
||||
|
||||
/// Set the IP Type of Service.
|
||||
/// @param [in] tos IP Type of Service.
|
||||
|
||||
void setIpToS(int tos);
|
||||
|
||||
/// 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);
|
||||
#endif
|
||||
|
||||
int ioctlQuery(int type) const;
|
||||
int sockoptQuery(int level, int option) const;
|
||||
int ioctlQuery(int type) const;
|
||||
int sockoptQuery(int level, int option) const;
|
||||
|
||||
const sockaddr* bindAddress() { return &m_BindAddr; }
|
||||
const sockaddr_any& bindAddressAny() { return m_BindAddr; }
|
||||
const sockaddr* bindAddress() { return m_BindAddr.get(); }
|
||||
const sockaddr_any& bindAddressAny() { return m_BindAddr; }
|
||||
|
||||
private:
|
||||
void setUDPSockOpt();
|
||||
void setUDPSockOpt();
|
||||
|
||||
private:
|
||||
const int m_iIPversion; // IP version
|
||||
int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test)
|
||||
UDPSOCKET m_iSocket; // socket descriptor
|
||||
|
||||
// Mutable because when querying original settings
|
||||
// this comprises the cache for extracted values,
|
||||
// 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
|
||||
|
||||
UDPSOCKET m_iSocket; // socket descriptor
|
||||
#ifdef SRT_ENABLE_IPOPTS
|
||||
int m_iIpTTL;
|
||||
int m_iIpToS;
|
||||
#endif
|
||||
int m_iSndBufSize; // UDP sending buffer size
|
||||
int m_iRcvBufSize; // UDP receiving buffer size
|
||||
int m_iIpV6Only; // IPV6_V6ONLY option (-1 if not set)
|
||||
sockaddr_any m_BindAddr;
|
||||
};
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif
|
||||
|
|
904
trunk/3rdparty/srt-1-fit/srtcore/common.cpp
vendored
904
trunk/3rdparty/srt-1-fit/srtcore/common.cpp
vendored
File diff suppressed because it is too large
Load diff
981
trunk/3rdparty/srt-1-fit/srtcore/common.h
vendored
981
trunk/3rdparty/srt-1-fit/srtcore/common.h
vendored
File diff suppressed because it is too large
Load diff
131
trunk/3rdparty/srt-1-fit/srtcore/congctl.cpp
vendored
131
trunk/3rdparty/srt-1-fit/srtcore/congctl.cpp
vendored
|
@ -12,7 +12,7 @@
|
|||
// This is a controversial thing, so temporarily blocking
|
||||
//#define SRT_ENABLE_SYSTEMBUFFER_TRACE
|
||||
|
||||
|
||||
#include "platform_sys.h"
|
||||
|
||||
|
||||
#ifdef SRT_ENABLE_SYSTEMBUFFER_TRACE
|
||||
|
@ -34,8 +34,11 @@
|
|||
#include "logging.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace srt::sync;
|
||||
using namespace srt_logging;
|
||||
|
||||
namespace srt {
|
||||
|
||||
SrtCongestionControlBase::SrtCongestionControlBase(CUDT* parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
@ -58,7 +61,7 @@ void SrtCongestion::Check()
|
|||
class LiveCC: public SrtCongestionControlBase
|
||||
{
|
||||
int64_t m_llSndMaxBW; //Max bandwidth (bytes/sec)
|
||||
size_t m_zSndAvgPayloadSize; //Average Payload Size of packets to xmit
|
||||
srt::sync::atomic<size_t> m_zSndAvgPayloadSize; //Average Payload Size of packets to xmit
|
||||
size_t m_zMaxPayloadSize;
|
||||
|
||||
// NAKREPORT stuff.
|
||||
|
@ -74,12 +77,12 @@ public:
|
|||
{
|
||||
m_llSndMaxBW = BW_INFINITE; // 1 Gbbps in Bytes/sec BW_INFINITE
|
||||
m_zMaxPayloadSize = parent->OPT_PayloadSize();
|
||||
if ( m_zMaxPayloadSize == 0 )
|
||||
if (m_zMaxPayloadSize == 0)
|
||||
m_zMaxPayloadSize = parent->maxPayloadSize();
|
||||
m_zSndAvgPayloadSize = m_zMaxPayloadSize;
|
||||
|
||||
m_iMinNakInterval_us = 20000; //Minimum NAK Report Period (usec)
|
||||
m_iNakReportAccel = 2; //Default NAK Report Period (RTT) accelerator
|
||||
m_iNakReportAccel = 2; //Default NAK Report Period (RTT) accelerator (send periodic NAK every RTT/2)
|
||||
|
||||
HLOGC(cclog.Debug, log << "Creating LiveCC: bw=" << m_llSndMaxBW << " avgplsize=" << m_zSndAvgPayloadSize);
|
||||
|
||||
|
@ -90,11 +93,11 @@ public:
|
|||
// from receiving thread.
|
||||
parent->ConnectSignal(TEV_SEND, SSLOT(updatePayloadSize));
|
||||
|
||||
/*
|
||||
* Readjust the max SndPeriod onACK (and onTimeout)
|
||||
*/
|
||||
parent->ConnectSignal(TEV_CHECKTIMER, SSLOT(updatePktSndPeriod_onTimer));
|
||||
parent->ConnectSignal(TEV_ACK, SSLOT(updatePktSndPeriod_onAck));
|
||||
//
|
||||
// Adjust the max SndPeriod onACK and onTimeout.
|
||||
//
|
||||
parent->ConnectSignal(TEV_CHECKTIMER, SSLOT(onRTO));
|
||||
parent->ConnectSignal(TEV_ACK, SSLOT(onAck));
|
||||
}
|
||||
|
||||
bool checkTransArgs(SrtCongestion::TransAPI api, SrtCongestion::TransDir dir, const char* , size_t size, int , bool ) ATR_OVERRIDE
|
||||
|
@ -151,24 +154,30 @@ private:
|
|||
HLOGC(cclog.Debug, log << "LiveCC: avg payload size updated: " << m_zSndAvgPayloadSize);
|
||||
}
|
||||
|
||||
void updatePktSndPeriod_onTimer(ETransmissionEvent , EventVariant var)
|
||||
/// @brief On RTO event update an inter-packet send interval.
|
||||
/// @param arg EventVariant::STAGE to distinguish between INIT and actual RTO.
|
||||
void onRTO(ETransmissionEvent , EventVariant var)
|
||||
{
|
||||
if ( var.get<EventVariant::STAGE>() != TEV_CHT_INIT )
|
||||
if (var.get<EventVariant::STAGE>() != TEV_CHT_INIT )
|
||||
updatePktSndPeriod();
|
||||
}
|
||||
|
||||
void updatePktSndPeriod_onAck(ETransmissionEvent , EventVariant )
|
||||
/// @brief Handle an incoming ACK event.
|
||||
/// Mainly updates a send interval between packets relying on the maximum BW limit.
|
||||
void onAck(ETransmissionEvent, EventVariant )
|
||||
{
|
||||
updatePktSndPeriod();
|
||||
}
|
||||
|
||||
/// @brief Updates a send interval between packets relying on the maximum BW limit.
|
||||
void updatePktSndPeriod()
|
||||
{
|
||||
// packet = payload + header
|
||||
const double pktsize = (double) m_zSndAvgPayloadSize + CPacket::SRT_DATA_HDR_SIZE;
|
||||
const double pktsize = (double) m_zSndAvgPayloadSize.load() + CPacket::SRT_DATA_HDR_SIZE;
|
||||
m_dPktSndPeriod = 1000 * 1000.0 * (pktsize / m_llSndMaxBW);
|
||||
HLOGC(cclog.Debug, log << "LiveCC: sending period updated: " << m_dPktSndPeriod
|
||||
<< " (pktsize=" << pktsize << ", bw=" << m_llSndMaxBW);
|
||||
<< " by avg pktsize=" << m_zSndAvgPayloadSize
|
||||
<< ", bw=" << m_llSndMaxBW);
|
||||
}
|
||||
|
||||
void setMaxBW(int64_t maxbw)
|
||||
|
@ -176,7 +185,6 @@ private:
|
|||
m_llSndMaxBW = maxbw > 0 ? maxbw : BW_INFINITE;
|
||||
updatePktSndPeriod();
|
||||
|
||||
#ifdef SRT_ENABLE_NOCWND
|
||||
/*
|
||||
* UDT default flow control should not trigger under normal SRT operation
|
||||
* UDT stops sending if the number of packets in transit (not acknowledged)
|
||||
|
@ -186,9 +194,6 @@ private:
|
|||
*/
|
||||
// XXX Consider making this a socket option.
|
||||
m_dCWndSize = m_dMaxCWndSize;
|
||||
#else
|
||||
m_dCWndSize = 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateBandwidth(int64_t maxbw, int64_t bw) ATR_OVERRIDE
|
||||
|
@ -215,7 +220,7 @@ private:
|
|||
return SrtCongestion::SRM_FASTREXMIT;
|
||||
}
|
||||
|
||||
uint64_t updateNAKInterval(uint64_t nakint_tk, int /*rcv_speed*/, size_t /*loss_length*/) ATR_OVERRIDE
|
||||
int64_t updateNAKInterval(int64_t nakint_us, int /*rcv_speed*/, size_t /*loss_length*/) ATR_OVERRIDE
|
||||
{
|
||||
/*
|
||||
* duB:
|
||||
|
@ -225,7 +230,7 @@ private:
|
|||
* For realtime Transport Stream content, pkts/sec is not a good indication of time to transmit
|
||||
* since packets are not filled to m_iMSS and packet size average is lower than (7*188)
|
||||
* for low bit rates.
|
||||
* If NAK report is lost, another cycle (RTT) is requred which is bad for low latency so we
|
||||
* If NAK report is lost, another cycle (RTT) is required which is bad for low latency so we
|
||||
* accelerate the NAK Reports frequency, at the cost of possible duplicate resend.
|
||||
* Finally, the UDT4 native minimum NAK interval (m_ullMinNakInt_tk) is 300 ms which is too high
|
||||
* (~10 i30 video frames) to maintain low latency.
|
||||
|
@ -233,12 +238,12 @@ private:
|
|||
|
||||
// Note: this value will still be reshaped to defined minimum,
|
||||
// as per minNAKInterval.
|
||||
return nakint_tk / m_iNakReportAccel;
|
||||
return nakint_us / m_iNakReportAccel;
|
||||
}
|
||||
|
||||
uint64_t minNAKInterval() ATR_OVERRIDE
|
||||
int64_t minNAKInterval() ATR_OVERRIDE
|
||||
{
|
||||
return m_iMinNakInterval_us * CTimer::getCPUFrequency();
|
||||
return m_iMinNakInterval_us;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -250,7 +255,7 @@ class FileCC : public SrtCongestionControlBase
|
|||
|
||||
// Fields from CUDTCC
|
||||
int m_iRCInterval; // UDT Rate control interval
|
||||
uint64_t m_LastRCTime; // last rate increase time
|
||||
steady_clock::time_point m_LastRCTime; // last rate increase time
|
||||
bool m_bSlowStart; // if in slow start phase
|
||||
int32_t m_iLastAck; // last ACKed seq no
|
||||
bool m_bLoss; // if loss happened since last rate increase
|
||||
|
@ -268,7 +273,7 @@ public:
|
|||
FileCC(CUDT* parent)
|
||||
: SrtCongestionControlBase(parent)
|
||||
, m_iRCInterval(CUDT::COMM_SYN_INTERVAL_US)
|
||||
, m_LastRCTime(CTimer::getTime())
|
||||
, m_LastRCTime(steady_clock::now())
|
||||
, m_bSlowStart(true)
|
||||
, m_iLastAck(parent->sndSeqNo())
|
||||
, m_bLoss(false)
|
||||
|
@ -290,9 +295,9 @@ public:
|
|||
m_dCWndSize = 16;
|
||||
m_dPktSndPeriod = 1;
|
||||
|
||||
parent->ConnectSignal(TEV_ACK, SSLOT(updateSndPeriod));
|
||||
parent->ConnectSignal(TEV_LOSSREPORT, SSLOT(slowdownSndPeriod));
|
||||
parent->ConnectSignal(TEV_CHECKTIMER, SSLOT(speedupToWindowSize));
|
||||
parent->ConnectSignal(TEV_ACK, SSLOT(onACK));
|
||||
parent->ConnectSignal(TEV_LOSSREPORT, SSLOT(onLossReport));
|
||||
parent->ConnectSignal(TEV_CHECKTIMER, SSLOT(onRTO));
|
||||
|
||||
HLOGC(cclog.Debug, log << "Creating FileCC");
|
||||
}
|
||||
|
@ -306,10 +311,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Tells if an early ACK is needed (before the next Full ACK happening every 10ms).
|
||||
/// In FileCC, treat non-full-payload as an end-of-message (stream)
|
||||
/// and request ACK to be sent immediately.
|
||||
bool needsQuickACK(const CPacket& pkt) ATR_OVERRIDE
|
||||
{
|
||||
// For FileCC, treat non-full-buffer situation as an end-of-message situation;
|
||||
// request ACK to be sent immediately.
|
||||
if (pkt.getLength() < m_parent->maxPayloadSize())
|
||||
{
|
||||
// This is not a regular fixed size packet...
|
||||
|
@ -330,14 +336,15 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
// SLOTS
|
||||
void updateSndPeriod(ETransmissionEvent, EventVariant arg)
|
||||
/// Handle icoming ACK event.
|
||||
/// In slow start stage increase CWND. Leave slow start once maximum CWND is reached.
|
||||
/// In congestion avoidance stage adjust inter packet send interval value to achieve maximum rate.
|
||||
void onACK(ETransmissionEvent, EventVariant arg)
|
||||
{
|
||||
const int ack = arg.get<EventVariant::ACK>();
|
||||
|
||||
const uint64_t currtime = CTimer::getTime();
|
||||
if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval)
|
||||
const steady_clock::time_point currtime = steady_clock::now();
|
||||
if (count_microseconds(currtime - m_LastRCTime) < m_iRCInterval)
|
||||
return;
|
||||
|
||||
m_LastRCTime = currtime;
|
||||
|
@ -360,11 +367,11 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->RTT() + m_iRCInterval);
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->SRTT() + m_iRCInterval);
|
||||
HLOGC(cclog.Debug, log << "FileCC: UPD (slowstart:ENDED) wndsize="
|
||||
<< m_dCWndSize << "/" << m_dMaxCWndSize
|
||||
<< " sndperiod=" << m_dPktSndPeriod << "us = wndsize/(RTT+RCIV) RTT="
|
||||
<< m_parent->RTT() << " RCIV=" << m_iRCInterval);
|
||||
<< m_parent->SRTT() << " RCIV=" << m_iRCInterval);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -376,9 +383,9 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_dCWndSize = m_parent->deliveryRate() / 1000000.0 * (m_parent->RTT() + m_iRCInterval) + 16;
|
||||
m_dCWndSize = m_parent->deliveryRate() / 1000000.0 * (m_parent->SRTT() + m_iRCInterval) + 16;
|
||||
HLOGC(cclog.Debug, log << "FileCC: UPD (speed mode) wndsize="
|
||||
<< m_dCWndSize << "/" << m_dMaxCWndSize << " RTT = " << m_parent->RTT()
|
||||
<< m_dCWndSize << "/" << m_dMaxCWndSize << " RTT = " << m_parent->SRTT()
|
||||
<< " sndperiod=" << m_dPktSndPeriod << "us. deliverRate = "
|
||||
<< m_parent->deliveryRate() << " pkts/s)");
|
||||
}
|
||||
|
@ -393,7 +400,7 @@ private:
|
|||
else
|
||||
{
|
||||
double inc = 0;
|
||||
const int loss_bw = 2 * (1000000 / m_dLastDecPeriod); // 2 times last loss point
|
||||
const int loss_bw = static_cast<int>(2 * (1000000 / m_dLastDecPeriod)); // 2 times last loss point
|
||||
const int bw_pktps = min(loss_bw, m_parent->bandwidth());
|
||||
|
||||
int64_t B = (int64_t)(bw_pktps - 1000000.0 / m_dPktSndPeriod);
|
||||
|
@ -456,9 +463,10 @@ private:
|
|||
|
||||
}
|
||||
|
||||
// When a lossreport has been received, it might be due to having
|
||||
// reached the available bandwidth limit. Slowdown to avoid further losses.
|
||||
void slowdownSndPeriod(ETransmissionEvent, EventVariant arg)
|
||||
/// When a lossreport has been received, it might be due to having
|
||||
/// reached the available bandwidth limit. Slowdown to avoid further losses.
|
||||
/// Leave the slow start stage if it was active.
|
||||
void onLossReport(ETransmissionEvent, EventVariant arg)
|
||||
{
|
||||
const int32_t* losslist = arg.get_ptr();
|
||||
size_t losslist_size = arg.get_len();
|
||||
|
@ -483,9 +491,9 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->RTT() + m_iRCInterval);
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->SRTT() + m_iRCInterval);
|
||||
HLOGC(cclog.Debug, log << "FileCC: LOSS, SLOWSTART:OFF, sndperiod=" << m_dPktSndPeriod << "us AS wndsize/(RTT+RCIV) (RTT="
|
||||
<< m_parent->RTT() << " RCIV=" << m_iRCInterval << ")");
|
||||
<< m_parent->SRTT() << " RCIV=" << m_iRCInterval << ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -493,14 +501,14 @@ private:
|
|||
m_bLoss = true;
|
||||
|
||||
// TODO: const int pktsInFlight = CSeqNo::seqoff(m_iLastAck, m_parent->sndSeqNo());
|
||||
const int pktsInFlight = m_parent->RTT() / m_dPktSndPeriod;
|
||||
const int pktsInFlight = static_cast<int>(m_parent->SRTT() / m_dPktSndPeriod);
|
||||
const int numPktsLost = m_parent->sndLossLength();
|
||||
const int lost_pcent_x10 = pktsInFlight > 0 ? (numPktsLost * 1000) / pktsInFlight : 0;
|
||||
|
||||
HLOGC(cclog.Debug, log << "FileCC: LOSS: "
|
||||
<< "sent=" << CSeqNo::seqlen(m_iLastAck, m_parent->sndSeqNo()) << ", inFlight=" << pktsInFlight
|
||||
<< ", lost=" << numPktsLost << " ("
|
||||
<< lost_pcent_x10 / 10 << "." << lost_pcent_x10 % 10 << "\%)");
|
||||
<< lost_pcent_x10 / 10 << "." << lost_pcent_x10 % 10 << "%)");
|
||||
if (lost_pcent_x10 < 20) // 2.0%
|
||||
{
|
||||
HLOGC(cclog.Debug, log << "FileCC: LOSS: m_dLastDecPeriod=" << m_dLastDecPeriod << "->" << m_dPktSndPeriod);
|
||||
|
@ -527,11 +535,8 @@ private:
|
|||
|
||||
m_iLastDecSeq = m_parent->sndSeqNo();
|
||||
|
||||
// remove global synchronization using randomization
|
||||
srand(m_iLastDecSeq);
|
||||
m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
|
||||
if (m_iDecRandom < 1)
|
||||
m_iDecRandom = 1;
|
||||
m_iDecRandom = m_iAvgNAKNum > 1 ? genRandomInt(1, m_iAvgNAKNum) : 1;
|
||||
SRT_ASSERT(m_iDecRandom >= 1);
|
||||
HLOGC(cclog.Debug, log << "FileCC: LOSS:NEW lseqno=" << lossbegin
|
||||
<< ", lastsentseqno=" << m_iLastDecSeq
|
||||
<< ", seqdiff=" << CSeqNo::seqoff(m_iLastDecSeq, lossbegin)
|
||||
|
@ -562,7 +567,9 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void speedupToWindowSize(ETransmissionEvent, EventVariant arg)
|
||||
/// @brief On retransmission timeout leave slow start stage if it was active.
|
||||
/// @param arg EventVariant::STAGE to distinguish between INIT and actual RTO.
|
||||
void onRTO(ETransmissionEvent, EventVariant arg)
|
||||
{
|
||||
ECheckTimerStage stg = arg.get<EventVariant::STAGE>();
|
||||
|
||||
|
@ -583,9 +590,9 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->RTT() + m_iRCInterval);
|
||||
m_dPktSndPeriod = m_dCWndSize / (m_parent->SRTT() + m_iRCInterval);
|
||||
HLOGC(cclog.Debug, log << "FileCC: CHKTIMER, SLOWSTART:OFF, sndperiod=" << m_dPktSndPeriod << "us AS wndsize/(RTT+RCIV) (wndsize="
|
||||
<< setprecision(6) << m_dCWndSize << " RTT=" << m_parent->RTT() << " RCIV=" << m_iRCInterval << ")");
|
||||
<< setprecision(6) << m_dCWndSize << " RTT=" << m_parent->SRTT() << " RCIV=" << m_iRCInterval << ")");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -636,8 +643,18 @@ bool SrtCongestion::configure(CUDT* parent)
|
|||
return !!congctl;
|
||||
}
|
||||
|
||||
void SrtCongestion::dispose()
|
||||
{
|
||||
if (congctl)
|
||||
{
|
||||
delete congctl;
|
||||
congctl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SrtCongestion::~SrtCongestion()
|
||||
{
|
||||
delete congctl;
|
||||
congctl = 0;
|
||||
dispose();
|
||||
}
|
||||
|
||||
} // namespace srt
|
||||
|
|
62
trunk/3rdparty/srt-1-fit/srtcore/congctl.h
vendored
62
trunk/3rdparty/srt-1-fit/srtcore/congctl.h
vendored
|
@ -8,17 +8,19 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef INC__CONGCTL_H
|
||||
#define INC__CONGCTL_H
|
||||
#ifndef INC_SRT_CONGCTL_H
|
||||
#define INC_SRT_CONGCTL_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace srt {
|
||||
|
||||
class CUDT;
|
||||
class SrtCongestionControlBase;
|
||||
|
||||
typedef SrtCongestionControlBase* srtcc_create_t(CUDT* parent);
|
||||
typedef SrtCongestionControlBase* srtcc_create_t(srt::CUDT* parent);
|
||||
|
||||
class SrtCongestion
|
||||
{
|
||||
|
@ -50,18 +52,29 @@ public:
|
|||
|
||||
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; }
|
||||
};
|
||||
|
||||
static NamePtr* find(const std::string& name)
|
||||
{
|
||||
NamePtr* end = congctls+N_CONTROLLERS;
|
||||
NamePtr* try_selector = std::find_if(congctls, end, IsName(name));
|
||||
return try_selector != end ? try_selector : NULL;
|
||||
}
|
||||
|
||||
static bool exists(const std::string& name)
|
||||
{
|
||||
return find(name);
|
||||
}
|
||||
|
||||
// You can call select() multiple times, until finally
|
||||
// the 'configure' method is called.
|
||||
bool select(const std::string& name)
|
||||
{
|
||||
NamePtr* end = congctls+N_CONTROLLERS;
|
||||
NamePtr* try_selector = std::find_if(congctls, end, IsName(name));
|
||||
if (try_selector == end)
|
||||
NamePtr* try_selector = find(name);
|
||||
if (!try_selector)
|
||||
return false;
|
||||
selector = try_selector - congctls;
|
||||
return true;
|
||||
|
@ -79,12 +92,18 @@ public:
|
|||
// 1. The congctl is individual, so don't copy it. Set NULL.
|
||||
// 2. The selected name is copied so that it's configured correctly.
|
||||
SrtCongestion(const SrtCongestion& source): congctl(), selector(source.selector) {}
|
||||
void operator=(const SrtCongestion& source) { congctl = 0; selector = source.selector; }
|
||||
|
||||
// This function will be called by the parent CUDT
|
||||
// in appropriate time. It should select appropriate
|
||||
// congctl basing on the value in selector, then
|
||||
// pin oneself in into CUDT for receiving event signals.
|
||||
bool configure(CUDT* parent);
|
||||
bool configure(srt::CUDT* parent);
|
||||
|
||||
// This function will intentionally delete the contained object.
|
||||
// This makes future calls to ready() return false. Calling
|
||||
// configure on it again will create it again.
|
||||
void dispose();
|
||||
|
||||
// Will delete the pinned in congctl object.
|
||||
// This must be defined in *.cpp file due to virtual
|
||||
|
@ -111,12 +130,13 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
class CPacket;
|
||||
|
||||
class SrtCongestionControlBase
|
||||
{
|
||||
protected:
|
||||
// Here can be some common fields
|
||||
CUDT* m_parent;
|
||||
srt::CUDT* m_parent;
|
||||
|
||||
double m_dPktSndPeriod;
|
||||
double m_dCWndSize;
|
||||
|
@ -127,11 +147,11 @@ protected:
|
|||
//int m_iMSS; // NOT REQUIRED. Use m_parent->MSS() instead.
|
||||
//int32_t m_iSndCurrSeqNo; // NOT REQUIRED. Use m_parent->sndSeqNo().
|
||||
//int m_iRcvRate; // NOT REQUIRED. Use m_parent->deliveryRate() instead.
|
||||
//int m_RTT; // NOT REQUIRED. Use m_parent->RTT() instead.
|
||||
//int m_RTT; // NOT REQUIRED. Use m_parent->SRTT() instead.
|
||||
//char* m_pcParam; // Used to access m_llMaxBw. Use m_parent->maxBandwidth() instead.
|
||||
|
||||
// Constructor in protected section so that this class is semi-abstract.
|
||||
SrtCongestionControlBase(CUDT* parent);
|
||||
SrtCongestionControlBase(srt::CUDT* parent);
|
||||
public:
|
||||
|
||||
// This could be also made abstract, but this causes a linkage
|
||||
|
@ -169,11 +189,11 @@ public:
|
|||
virtual int ACKTimeout_us() const { return 0; }
|
||||
|
||||
// Called when the settings concerning m_llMaxBW were changed.
|
||||
// Arg 1: value of CUDT::m_llMaxBW
|
||||
// Arg 2: value calculated out of CUDT::m_llInputBW and CUDT::m_iOverheadBW.
|
||||
// Arg 1: value of CUDT's m_config.m_llMaxBW
|
||||
// Arg 2: value calculated out of CUDT's m_config.llInputBW and m_config.iOverheadBW.
|
||||
virtual void updateBandwidth(int64_t, int64_t) {}
|
||||
|
||||
virtual bool needsQuickACK(const CPacket&)
|
||||
virtual bool needsQuickACK(const srt::CPacket&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -186,21 +206,21 @@ public:
|
|||
|
||||
virtual SrtCongestion::RexmitMethod rexmitMethod() = 0; // Implementation enforced.
|
||||
|
||||
virtual uint64_t updateNAKInterval(uint64_t nakint_tk, int rcv_speed, size_t loss_length)
|
||||
virtual int64_t updateNAKInterval(int64_t nakint_us, int rcv_speed, size_t loss_length)
|
||||
{
|
||||
if (rcv_speed > 0)
|
||||
nakint_tk += (loss_length * uint64_t(1000000) / rcv_speed) * CTimer::getCPUFrequency();
|
||||
nakint_us += (loss_length * int64_t(1000000) / rcv_speed);
|
||||
|
||||
return nakint_tk;
|
||||
return nakint_us;
|
||||
}
|
||||
|
||||
virtual uint64_t minNAKInterval()
|
||||
virtual int64_t minNAKInterval()
|
||||
{
|
||||
return 0; // Leave default
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif
|
||||
|
|
10745
trunk/3rdparty/srt-1-fit/srtcore/core.cpp
vendored
10745
trunk/3rdparty/srt-1-fit/srtcore/core.cpp
vendored
File diff suppressed because it is too large
Load diff
1064
trunk/3rdparty/srt-1-fit/srtcore/core.h
vendored
1064
trunk/3rdparty/srt-1-fit/srtcore/core.h
vendored
File diff suppressed because it is too large
Load diff
420
trunk/3rdparty/srt-1-fit/srtcore/crypto.cpp
vendored
420
trunk/3rdparty/srt-1-fit/srtcore/crypto.cpp
vendored
|
@ -13,6 +13,8 @@ written by
|
|||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "platform_sys.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
@ -24,6 +26,7 @@ written by
|
|||
#include "crypto.h"
|
||||
#include "logging.h"
|
||||
#include "core.h"
|
||||
#include "api.h"
|
||||
|
||||
using namespace srt_logging;
|
||||
|
||||
|
@ -40,9 +43,10 @@ using namespace srt_logging;
|
|||
*/
|
||||
|
||||
// 10* HAICRYPT_DEF_KM_PRE_ANNOUNCE
|
||||
const int SRT_CRYPT_KM_PRE_ANNOUNCE = 0x10000;
|
||||
const int SRT_CRYPT_KM_PRE_ANNOUNCE SRT_ATR_UNUSED = 0x10000;
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
namespace srt_logging
|
||||
{
|
||||
std::string KmStateStr(SRT_KM_STATE state)
|
||||
{
|
||||
switch (state)
|
||||
|
@ -53,18 +57,46 @@ std::string KmStateStr(SRT_KM_STATE state)
|
|||
TAKE(SECURING);
|
||||
TAKE(NOSECRET);
|
||||
TAKE(BADSECRET);
|
||||
#ifdef ENABLE_AEAD_API_PREVIEW
|
||||
TAKE(BADCRYPTOMODE);
|
||||
#endif
|
||||
#undef TAKE
|
||||
default:
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "??? (%d)", state);
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
_snprintf(buf, sizeof(buf) - 1, "??? (%d)", state);
|
||||
#else
|
||||
snprintf(buf, sizeof(buf), "??? (%d)", state);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using srt_logging::KmStateStr;
|
||||
|
||||
std::string CCryptoControl::FormatKmMessage(std::string hdr, int cmd, size_t srtlen)
|
||||
void srt::CCryptoControl::globalInit()
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
// We need to force the Cryspr to be initialized during startup to avoid the
|
||||
// possibility of multiple threads initialzing the same static data later on.
|
||||
HaiCryptCryspr_Get_Instance();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool srt::CCryptoControl::isAESGCMSupported()
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
return HaiCrypt_IsAESGCM_Supported() != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
std::string srt::CCryptoControl::FormatKmMessage(std::string hdr, int cmd, size_t srtlen)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << hdr << ": cmd=" << cmd << "(" << (cmd == SRT_CMD_KMREQ ? "KMREQ":"KMRSP") <<") len="
|
||||
|
@ -75,7 +107,7 @@ std::string CCryptoControl::FormatKmMessage(std::string hdr, int cmd, size_t srt
|
|||
}
|
||||
#endif
|
||||
|
||||
void CCryptoControl::updateKmState(int cmd, size_t srtlen SRT_ATR_UNUSED)
|
||||
void srt::CCryptoControl::updateKmState(int cmd, size_t srtlen SRT_ATR_UNUSED)
|
||||
{
|
||||
if (cmd == SRT_CMD_KMREQ)
|
||||
{
|
||||
|
@ -83,61 +115,63 @@ void CCryptoControl::updateKmState(int cmd, size_t srtlen SRT_ATR_UNUSED)
|
|||
{
|
||||
m_SndKmState = SRT_KM_S_SECURING;
|
||||
}
|
||||
LOGP(mglog.Note, FormatKmMessage("sendSrtMsg", cmd, srtlen));
|
||||
LOGP(cnlog.Note, FormatKmMessage("sendSrtMsg", cmd, srtlen));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGP(mglog.Note, FormatKmMessage("sendSrtMsg", cmd, srtlen));
|
||||
LOGP(cnlog.Note, FormatKmMessage("sendSrtMsg", cmd, srtlen));
|
||||
}
|
||||
}
|
||||
|
||||
void CCryptoControl::createFakeSndContext()
|
||||
void srt::CCryptoControl::createFakeSndContext()
|
||||
{
|
||||
if (!m_iSndKmKeyLen)
|
||||
m_iSndKmKeyLen = 16;
|
||||
|
||||
if (!createCryptoCtx(Ref(m_hSndCrypto), m_iSndKmKeyLen, HAICRYPT_CRYPTO_DIR_TX))
|
||||
if (!createCryptoCtx((m_hSndCrypto), m_iSndKmKeyLen, HAICRYPT_CRYPTO_DIR_TX, false))
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "Error: Can't create fake crypto context for sending - sending will return ERROR!");
|
||||
HLOGC(cnlog.Debug, log << "Error: Can't create fake crypto context for sending - sending will return ERROR!");
|
||||
m_hSndCrypto = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CCryptoControl::processSrtMsg_KMREQ(
|
||||
int srt::CCryptoControl::processSrtMsg_KMREQ(
|
||||
const uint32_t* srtdata SRT_ATR_UNUSED,
|
||||
size_t bytelen SRT_ATR_UNUSED,
|
||||
uint32_t* srtdata_out, ref_t<size_t> r_srtlen, int hsv SRT_ATR_UNUSED)
|
||||
int hsv SRT_ATR_UNUSED,
|
||||
uint32_t pw_srtdata_out[], size_t& w_srtlen)
|
||||
{
|
||||
size_t& srtlen = *r_srtlen;
|
||||
//Receiver
|
||||
/* All 32-bit msg fields swapped on reception
|
||||
* But HaiCrypt expect network order message
|
||||
* Re-swap to cancel it.
|
||||
*/
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
srtlen = bytelen/sizeof(srtdata[SRT_KMR_KMSTATE]);
|
||||
HtoNLA(srtdata_out, srtdata, srtlen);
|
||||
unsigned char* kmdata = reinterpret_cast<unsigned char*>(srtdata_out);
|
||||
|
||||
std::vector<unsigned char> kmcopy(kmdata, kmdata + bytelen);
|
||||
w_srtlen = bytelen/sizeof(srtdata[SRT_KMR_KMSTATE]);
|
||||
HtoNLA((pw_srtdata_out), srtdata, w_srtlen);
|
||||
unsigned char* kmdata = reinterpret_cast<unsigned char*>(pw_srtdata_out);
|
||||
|
||||
// The side that has received KMREQ is always an HSD_RESPONDER, regardless of
|
||||
// what has called this function. The HSv5 handshake only enforces bidirectional
|
||||
// connection.
|
||||
|
||||
bool bidirectional = hsv > CUDT::HS_VERSION_UDT4;
|
||||
const bool bidirectional = hsv > CUDT::HS_VERSION_UDT4;
|
||||
|
||||
// Local macro to return rejection appropriately.
|
||||
// CHANGED. The first version made HSv5 reject the connection.
|
||||
// This isn't well handled by applications, so the connection is
|
||||
// still established, but unable to handle any transport.
|
||||
//#define KMREQ_RESULT_REJECTION() if (bidirectional) { return SRT_CMD_NONE; } else { srtlen = 1; goto HSv4_ErrorReport; }
|
||||
#define KMREQ_RESULT_REJECTION() { srtlen = 1; goto HSv4_ErrorReport; }
|
||||
//#define KMREQ_RESULT_REJECTION() if (bidirectional) { return SRT_CMD_NONE; } else { w_srtlen = 1; goto HSv4_ErrorReport; }
|
||||
#define KMREQ_RESULT_REJECTION() { w_srtlen = 1; goto HSv4_ErrorReport; }
|
||||
|
||||
int rc = HAICRYPT_OK; // needed before 'goto' run from KMREQ_RESULT_REJECTION macro
|
||||
bool SRT_ATR_UNUSED wasb4 = false;
|
||||
bool wasb4 SRT_ATR_UNUSED = false;
|
||||
size_t sek_len = 0;
|
||||
|
||||
const bool bUseGCM =
|
||||
(m_iCryptoMode == CSrtConfig::CIPHER_MODE_AUTO && kmdata[HCRYPT_MSG_KM_OFS_CIPHER] == HCRYPT_CIPHER_AES_GCM) ||
|
||||
(m_iCryptoMode == CSrtConfig::CIPHER_MODE_AES_GCM);
|
||||
|
||||
// What we have to do:
|
||||
// If encryption is on (we know that by having m_KmSecret nonempty), create
|
||||
// the crypto context (if bidirectional, create for both sending and receiving).
|
||||
|
@ -147,16 +181,16 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
// function normally return SRT_CMD_KMRSP.
|
||||
if ( bytelen <= HCRYPT_MSG_KM_OFS_SALT ) //Sanity on message
|
||||
{
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: size of the KM (" << bytelen << ") is too small, must be >" << HCRYPT_MSG_KM_OFS_SALT);
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMREQ: size of the KM (" << bytelen << ") is too small, must be >" << HCRYPT_MSG_KM_OFS_SALT);
|
||||
m_RcvKmState = SRT_KM_S_BADSECRET;
|
||||
KMREQ_RESULT_REJECTION();
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << "KMREQ: getting SEK and creating receiver crypto");
|
||||
HLOGC(cnlog.Debug, log << "KMREQ: getting SEK and creating receiver crypto");
|
||||
sek_len = hcryptMsg_KM_GetSekLen(kmdata);
|
||||
if ( sek_len == 0 )
|
||||
{
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: Received SEK is empty - REJECTING!");
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMREQ: Received SEK is empty - REJECTING!");
|
||||
m_RcvKmState = SRT_KM_S_BADSECRET;
|
||||
KMREQ_RESULT_REJECTION();
|
||||
}
|
||||
|
@ -168,7 +202,7 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
#if ENABLE_HEAVY_LOGGING
|
||||
if (m_iSndKmKeyLen != m_iRcvKmKeyLen)
|
||||
{
|
||||
LOGC(mglog.Debug, log << "processSrtMsg_KMREQ: Agent's PBKEYLEN=" << m_iSndKmKeyLen
|
||||
LOGC(cnlog.Debug, log << "processSrtMsg_KMREQ: Agent's PBKEYLEN=" << m_iSndKmKeyLen
|
||||
<< " overwritten by Peer's PBKEYLEN=" << m_iRcvKmKeyLen);
|
||||
}
|
||||
#endif
|
||||
|
@ -179,22 +213,25 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
// a wrong password.
|
||||
if (m_KmSecret.len == 0) //We have a shared secret <==> encryption is on
|
||||
{
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: Agent does not declare encryption - won't decrypt incoming packets!");
|
||||
LOGC(cnlog.Warn, log << "processSrtMsg_KMREQ: Agent does not declare encryption - won't decrypt incoming packets!");
|
||||
m_RcvKmState = SRT_KM_S_NOSECRET;
|
||||
KMREQ_RESULT_REJECTION();
|
||||
}
|
||||
wasb4 = m_hRcvCrypto;
|
||||
|
||||
if (!createCryptoCtx(Ref(m_hRcvCrypto), m_iRcvKmKeyLen, HAICRYPT_CRYPTO_DIR_RX))
|
||||
if (!createCryptoCtx((m_hRcvCrypto), m_iRcvKmKeyLen, HAICRYPT_CRYPTO_DIR_RX, bUseGCM))
|
||||
{
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: Can't create RCV CRYPTO CTX - must reject...");
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMREQ: Can't create RCV CRYPTO CTX - must reject...");
|
||||
m_RcvKmState = SRT_KM_S_NOSECRET;
|
||||
KMREQ_RESULT_REJECTION();
|
||||
}
|
||||
|
||||
// Deduce resulting mode.
|
||||
m_iCryptoMode = bUseGCM ? CSrtConfig::CIPHER_MODE_AES_GCM : CSrtConfig::CIPHER_MODE_AES_CTR;
|
||||
|
||||
if (!wasb4)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMREQ: created RX ENC with KeyLen=" << m_iRcvKmKeyLen);
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMREQ: created RX ENC with KeyLen=" << m_iRcvKmKeyLen);
|
||||
}
|
||||
// We have both sides set with password, so both are pending for security
|
||||
m_RcvKmState = SRT_KM_S_SECURING;
|
||||
|
@ -207,36 +244,44 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
{
|
||||
case HAICRYPT_OK:
|
||||
m_RcvKmState = SRT_KM_S_SECURED;
|
||||
HLOGC(mglog.Debug, log << "KMREQ/rcv: (snd) Rx process successful - SECURED.");
|
||||
HLOGC(cnlog.Debug, log << "KMREQ/rcv: (snd) Rx process successful - SECURED.");
|
||||
//Send back the whole message to confirm
|
||||
break;
|
||||
case HAICRYPT_ERROR_WRONG_SECRET: //Unmatched shared secret to decrypt wrapped key
|
||||
m_RcvKmState = m_SndKmState = SRT_KM_S_BADSECRET;
|
||||
//Send status KMRSP message to tel error
|
||||
srtlen = 1;
|
||||
LOGC(mglog.Error, log << "KMREQ/rcv: (snd) Rx process failure - BADSECRET");
|
||||
w_srtlen = 1;
|
||||
LOGC(cnlog.Warn, log << "KMREQ/rcv: (snd) Rx process failure - BADSECRET");
|
||||
break;
|
||||
case HAICRYPT_ERROR_CIPHER:
|
||||
#ifdef ENABLE_AEAD_API_PREVIEW
|
||||
m_RcvKmState = m_SndKmState = SRT_KM_S_BADCRYPTOMODE;
|
||||
#else
|
||||
m_RcvKmState = m_SndKmState = SRT_KM_S_BADSECRET; // Use "bad secret" as a fallback.
|
||||
#endif
|
||||
w_srtlen = 1;
|
||||
LOGC(cnlog.Warn, log << "KMREQ/rcv: (snd) Rx process failure - BADCRYPTOMODE");
|
||||
break;
|
||||
case HAICRYPT_ERROR: //Other errors
|
||||
default:
|
||||
m_RcvKmState = m_SndKmState = SRT_KM_S_NOSECRET;
|
||||
srtlen = 1;
|
||||
LOGC(mglog.Error, log << "KMREQ/rcv: (snd) Rx process failure (IPE) - NOSECRET");
|
||||
w_srtlen = 1;
|
||||
LOGC(cnlog.Warn, log << "KMREQ/rcv: (snd) Rx process failure (IPE) - NOSECRET");
|
||||
break;
|
||||
}
|
||||
|
||||
LOGP(mglog.Note, FormatKmMessage("processSrtMsg_KMREQ", SRT_CMD_KMREQ, bytelen));
|
||||
LOGP(cnlog.Note, FormatKmMessage("processSrtMsg_KMREQ", SRT_CMD_KMREQ, bytelen));
|
||||
|
||||
// Since now, when CCryptoControl::decrypt() encounters an error, it will print it, ONCE,
|
||||
// until the next KMREQ is received as a key regeneration.
|
||||
m_bErrorReported = false;
|
||||
|
||||
|
||||
if (srtlen == 1)
|
||||
if (w_srtlen == 1)
|
||||
goto HSv4_ErrorReport;
|
||||
|
||||
// Configure the sender context also, if it succeeded to configure the
|
||||
// receiver context and we are using bidirectional mode.
|
||||
if ( bidirectional )
|
||||
if (bidirectional)
|
||||
{
|
||||
// Note: 'bidirectional' means that we want a bidirectional key update,
|
||||
// which happens only and exclusively with HSv5 handshake - not when the
|
||||
|
@ -249,7 +294,7 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
m_iSndKmKeyLen = m_iRcvKmKeyLen;
|
||||
if (HaiCrypt_Clone(m_hRcvCrypto, HAICRYPT_CRYPTO_DIR_TX, &m_hSndCrypto) != HAICRYPT_OK)
|
||||
{
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: Can't create SND CRYPTO CTX - WILL NOT SEND-ENCRYPT correctly!");
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMREQ: Can't create SND CRYPTO CTX - WILL NOT SEND-ENCRYPT correctly!");
|
||||
if (hasPassphrase())
|
||||
m_SndKmState = SRT_KM_S_BADSECRET;
|
||||
else
|
||||
|
@ -260,30 +305,30 @@ int CCryptoControl::processSrtMsg_KMREQ(
|
|||
m_SndKmState = SRT_KM_S_SECURED;
|
||||
}
|
||||
|
||||
LOGC(mglog.Note, log << FormatKmMessage("processSrtMsg_KMREQ", SRT_CMD_KMREQ, bytelen)
|
||||
LOGC(cnlog.Note, log << FormatKmMessage("processSrtMsg_KMREQ", SRT_CMD_KMREQ, bytelen)
|
||||
<< " SndKeyLen=" << m_iSndKmKeyLen
|
||||
<< " TX CRYPTO CTX CLONED FROM RX"
|
||||
);
|
||||
|
||||
// Write the KM message into the field from which it will be next sent.
|
||||
memcpy(m_SndKmMsg[0].Msg, kmdata, bytelen);
|
||||
memcpy((m_SndKmMsg[0].Msg), kmdata, bytelen);
|
||||
m_SndKmMsg[0].MsgLen = bytelen;
|
||||
m_SndKmMsg[0].iPeerRetry = 0; // Don't start sending them upon connection :)
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMREQ: NOT cloning RX to TX crypto: already in "
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMREQ: NOT cloning RX to TX crypto: already in "
|
||||
<< KmStateStr(m_SndKmState) << " state");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGP(mglog.Debug, "processSrtMsg_KMREQ: NOT SECURED - not replaying failed security association to TX CRYPTO CTX");
|
||||
HLOGP(cnlog.Debug, "processSrtMsg_KMREQ: NOT SECURED - not replaying failed security association to TX CRYPTO CTX");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMREQ: NOT REPLAYING the key update to TX CRYPTO CTX.");
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMREQ: NOT REPLAYING the key update to TX CRYPTO CTX.");
|
||||
}
|
||||
|
||||
return SRT_CMD_KMRSP;
|
||||
|
@ -304,17 +349,17 @@ HSv4_ErrorReport:
|
|||
// It's ok that this is reported as error because this happens in a scenario,
|
||||
// when non-encryption-enabled SRT application is contacted by encryption-enabled SRT
|
||||
// application which tries to make a security association.
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMREQ: Encryption not enabled at compile time - must reject...");
|
||||
LOGC(cnlog.Warn, log << "processSrtMsg_KMREQ: Encryption not enabled at compile time - must reject...");
|
||||
m_RcvKmState = SRT_KM_S_NOSECRET;
|
||||
#endif
|
||||
|
||||
srtlen = 1;
|
||||
w_srtlen = 1;
|
||||
|
||||
srtdata_out[SRT_KMR_KMSTATE] = m_RcvKmState;
|
||||
pw_srtdata_out[SRT_KMR_KMSTATE] = m_RcvKmState;
|
||||
return SRT_CMD_KMRSP;
|
||||
}
|
||||
|
||||
int CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len, int /* XXX unused? hsv*/)
|
||||
int srt::CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len, int /* XXX unused? hsv*/)
|
||||
{
|
||||
/* All 32-bit msg fields (if present) swapped on reception
|
||||
* But HaiCrypt expect network order message
|
||||
|
@ -365,9 +410,17 @@ int CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len, int
|
|||
m_SndKmState = SRT_KM_S_UNSECURED;
|
||||
retstatus = 0;
|
||||
break;
|
||||
#ifdef ENABLE_AEAD_API_PREVIEW
|
||||
case SRT_KM_S_BADCRYPTOMODE:
|
||||
// The peer expects to use a different cryptographic mode (e.g. AES-GCM, not AES-CTR).
|
||||
m_RcvKmState = SRT_KM_S_BADCRYPTOMODE;
|
||||
m_SndKmState = SRT_KM_S_BADCRYPTOMODE;
|
||||
retstatus = -1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOGC(mglog.Fatal, log << "processSrtMsg_KMRSP: IPE: unknown peer error state: "
|
||||
LOGC(cnlog.Fatal, log << "processSrtMsg_KMRSP: IPE: unknown peer error state: "
|
||||
<< KmStateStr(peerstate) << " (" << int(peerstate) << ")");
|
||||
m_RcvKmState = SRT_KM_S_NOSECRET;
|
||||
m_SndKmState = SRT_KM_S_NOSECRET;
|
||||
|
@ -375,11 +428,11 @@ int CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len, int
|
|||
break;
|
||||
}
|
||||
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMRSP: received failure report. STATE: " << KmStateStr(m_RcvKmState));
|
||||
LOGC(cnlog.Warn, log << "processSrtMsg_KMRSP: received failure report. STATE: " << KmStateStr(m_RcvKmState));
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMRSP: received key response len=" << len);
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMRSP: received key response len=" << len);
|
||||
// XXX INSECURE << ": [" << FormatBinaryString((uint8_t*)srtd, len) << "]";
|
||||
bool key1 = getKmMsg_acceptResponse(0, srtd, len);
|
||||
bool key2 = true;
|
||||
|
@ -389,40 +442,41 @@ int CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len, int
|
|||
if (key1 || key2)
|
||||
{
|
||||
m_SndKmState = m_RcvKmState = SRT_KM_S_SECURED;
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMRSP: KM response matches " << (key1 ? "EVEN" : "ODD") << " key");
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMRSP: KM response matches " << (key1 ? "EVEN" : "ODD") << " key");
|
||||
retstatus = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retstatus = -1;
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMRSP: IPE??? KM response key matches no key");
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMRSP: IPE??? KM response key matches no key");
|
||||
/* XXX INSECURE
|
||||
LOGC(mglog.Error, log << "processSrtMsg_KMRSP: KM response: [" << FormatBinaryString((uint8_t*)srtd, len)
|
||||
LOGC(cnlog.Error, log << "processSrtMsg_KMRSP: KM response: [" << FormatBinaryString((uint8_t*)srtd, len)
|
||||
<< "] matches no key 0=[" << FormatBinaryString((uint8_t*)m_SndKmMsg[0].Msg, m_SndKmMsg[0].MsgLen)
|
||||
<< "] 1=[" << FormatBinaryString((uint8_t*)m_SndKmMsg[1].Msg, m_SndKmMsg[1].MsgLen) << "]");
|
||||
*/
|
||||
|
||||
m_SndKmState = m_RcvKmState = SRT_KM_S_BADSECRET;
|
||||
}
|
||||
HLOGC(mglog.Debug, log << "processSrtMsg_KMRSP: key[0]: len=" << m_SndKmMsg[0].MsgLen << " retry=" << m_SndKmMsg[0].iPeerRetry
|
||||
HLOGC(cnlog.Debug, log << "processSrtMsg_KMRSP: key[0]: len=" << m_SndKmMsg[0].MsgLen << " retry=" << m_SndKmMsg[0].iPeerRetry
|
||||
<< "; key[1]: len=" << m_SndKmMsg[1].MsgLen << " retry=" << m_SndKmMsg[1].iPeerRetry);
|
||||
}
|
||||
|
||||
LOGP(mglog.Note, FormatKmMessage("processSrtMsg_KMRSP", SRT_CMD_KMRSP, len));
|
||||
LOGP(cnlog.Note, FormatKmMessage("processSrtMsg_KMRSP", SRT_CMD_KMRSP, len));
|
||||
|
||||
return retstatus;
|
||||
}
|
||||
|
||||
void CCryptoControl::sendKeysToPeer(Whether2RegenKm regen SRT_ATR_UNUSED)
|
||||
void srt::CCryptoControl::sendKeysToPeer(CUDT* sock SRT_ATR_UNUSED, int iSRTT SRT_ATR_UNUSED)
|
||||
{
|
||||
if ( !m_hSndCrypto || m_SndKmState == SRT_KM_S_UNSECURED)
|
||||
sync::ScopedLock lck(m_mtxLock);
|
||||
if (!m_hSndCrypto || m_SndKmState == SRT_KM_S_UNSECURED)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "sendKeysToPeer: NOT sending/regenerating keys: "
|
||||
HLOGC(cnlog.Debug, log << "sendKeysToPeer: NOT sending/regenerating keys: "
|
||||
<< (m_hSndCrypto ? "CONNECTION UNSECURED" : "NO TX CRYPTO CTX created"));
|
||||
return;
|
||||
}
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
uint64_t now = 0;
|
||||
srt::sync::steady_clock::time_point now = srt::sync::steady_clock::now();
|
||||
/*
|
||||
* Crypto Key Distribution to peer:
|
||||
* If...
|
||||
|
@ -432,39 +486,28 @@ void CCryptoControl::sendKeysToPeer(Whether2RegenKm regen SRT_ATR_UNUSED)
|
|||
* - last sent Keying Material req should have been replied (RTT*1.5 elapsed);
|
||||
* then (re-)send handshake request.
|
||||
*/
|
||||
if ( ((m_SndKmMsg[0].iPeerRetry > 0) || (m_SndKmMsg[1].iPeerRetry > 0))
|
||||
&& ((m_SndKmLastTime + ((m_parent->RTT() * 3)/2)) <= (now = CTimer::getTime())))
|
||||
if (((m_SndKmMsg[0].iPeerRetry > 0) || (m_SndKmMsg[1].iPeerRetry > 0))
|
||||
&& ((m_SndKmLastTime + srt::sync::microseconds_from((iSRTT * 3)/2)) <= now))
|
||||
{
|
||||
for (int ki = 0; ki < 2; ki++)
|
||||
{
|
||||
if (m_SndKmMsg[ki].iPeerRetry > 0 && m_SndKmMsg[ki].MsgLen > 0)
|
||||
{
|
||||
m_SndKmMsg[ki].iPeerRetry--;
|
||||
HLOGC(mglog.Debug, log << "sendKeysToPeer: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen
|
||||
HLOGC(cnlog.Debug, log << "sendKeysToPeer: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen
|
||||
<< " retry(updated)=" << m_SndKmMsg[ki].iPeerRetry);
|
||||
m_SndKmLastTime = now;
|
||||
m_parent->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen/sizeof(uint32_t));
|
||||
sock->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (now == 0)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "sendKeysToPeer: NO KEYS RESENT, will " <<
|
||||
(regen ? "" : "NOT ") << "regenerate.");
|
||||
}
|
||||
|
||||
if (regen)
|
||||
regenCryptoKm(
|
||||
true, // send UMSG_EXT + SRT_CMD_KMREQ to the peer, if regenerated the key
|
||||
false // Do not apply the regenerated key to the to the receiver context
|
||||
); // regenerate and send
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
void CCryptoControl::regenCryptoKm(bool sendit, bool bidirectional)
|
||||
void srt::CCryptoControl::regenCryptoKm(CUDT* sock SRT_ATR_UNUSED, bool bidirectional SRT_ATR_UNUSED)
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
sync::ScopedLock lck(m_mtxLock);
|
||||
if (!m_hSndCrypto)
|
||||
return;
|
||||
|
||||
|
@ -473,8 +516,8 @@ void CCryptoControl::regenCryptoKm(bool sendit, bool bidirectional)
|
|||
int nbo = HaiCrypt_Tx_ManageKeys(m_hSndCrypto, out_p, out_len_p, 2);
|
||||
int sent = 0;
|
||||
|
||||
HLOGC(mglog.Debug, log << "regenCryptoKm: regenerating crypto keys nbo=" << nbo <<
|
||||
" THEN=" << (sendit ? "SEND" : "KEEP") << " DIR=" << (bidirectional ? "BOTH" : "SENDER"));
|
||||
HLOGC(cnlog.Debug, log << "regenCryptoKm: regenerating crypto keys nbo=" << nbo <<
|
||||
" THEN=" << (sock ? "SEND" : "KEEP") << " DIR=" << (bidirectional ? "BOTH" : "SENDER"));
|
||||
|
||||
for (int i = 0; i < nbo && i < 2; i++)
|
||||
{
|
||||
|
@ -491,71 +534,69 @@ void CCryptoControl::regenCryptoKm(bool sendit, bool bidirectional)
|
|||
{
|
||||
|
||||
uint8_t* oldkey SRT_ATR_UNUSED = m_SndKmMsg[ki].Msg;
|
||||
HLOGC(mglog.Debug, log << "new key[" << ki << "] index=" << kix
|
||||
HLOGC(cnlog.Debug, log << "new key[" << ki << "] index=" << kix
|
||||
<< " OLD=[" << m_SndKmMsg[ki].MsgLen << "]"
|
||||
<< FormatBinaryString(m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen)
|
||||
<< " NEW=[" << out_len_p[i] << "]"
|
||||
<< FormatBinaryString((const uint8_t*)out_p[i], out_len_p[i]));
|
||||
|
||||
/* New Keying material, send to peer */
|
||||
memcpy(m_SndKmMsg[ki].Msg, out_p[i], out_len_p[i]);
|
||||
memcpy((m_SndKmMsg[ki].Msg), out_p[i], out_len_p[i]);
|
||||
m_SndKmMsg[ki].MsgLen = out_len_p[i];
|
||||
m_SndKmMsg[ki].iPeerRetry = SRT_MAX_KMRETRY;
|
||||
|
||||
if (bidirectional && !sendit)
|
||||
if (bidirectional && !sock)
|
||||
{
|
||||
// "Send" this key also to myself, just to be applied to the receiver crypto,
|
||||
// exactly the same way how this key is interpreted on the peer side into its receiver crypto
|
||||
int rc = HaiCrypt_Rx_Process(m_hRcvCrypto, m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen, NULL, NULL, 0);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
LOGC(mglog.Fatal, log << "regenCryptoKm: IPE: applying key generated in snd crypto into rcv crypto: failed code=" << rc);
|
||||
LOGC(cnlog.Fatal, log << "regenCryptoKm: IPE: applying key generated in snd crypto into rcv crypto: failed code=" << rc);
|
||||
// The party won't be able to decrypt incoming data!
|
||||
// Not sure if anything has to be reported.
|
||||
}
|
||||
}
|
||||
|
||||
if (sendit)
|
||||
if (sock)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "regenCryptoKm: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen
|
||||
HLOGC(cnlog.Debug, log << "regenCryptoKm: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen
|
||||
<< " retry(updated)=" << m_SndKmMsg[ki].iPeerRetry);
|
||||
m_parent->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen/sizeof(uint32_t));
|
||||
sock->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t));
|
||||
sent++;
|
||||
}
|
||||
}
|
||||
else if (out_len_p[i] == 0)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "no key[" << ki << "] index=" << kix << ": not generated");
|
||||
HLOGC(cnlog.Debug, log << "no key[" << ki << "] index=" << kix << ": not generated");
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "no key[" << ki << "] index=" << kix << ": key unchanged");
|
||||
HLOGC(cnlog.Debug, log << "no key[" << ki << "] index=" << kix << ": key unchanged");
|
||||
}
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << "regenCryptoKm: key[0]: len=" << m_SndKmMsg[0].MsgLen << " retry=" << m_SndKmMsg[0].iPeerRetry
|
||||
HLOGC(cnlog.Debug, log << "regenCryptoKm: key[0]: len=" << m_SndKmMsg[0].MsgLen << " retry=" << m_SndKmMsg[0].iPeerRetry
|
||||
<< "; key[1]: len=" << m_SndKmMsg[1].MsgLen << " retry=" << m_SndKmMsg[1].iPeerRetry);
|
||||
|
||||
if (sent)
|
||||
m_SndKmLastTime = CTimer::getTime();
|
||||
}
|
||||
m_SndKmLastTime = srt::sync::steady_clock::now();
|
||||
#endif
|
||||
}
|
||||
|
||||
CCryptoControl::CCryptoControl(CUDT* parent, SRTSOCKET id):
|
||||
m_parent(parent), // should be initialized in createCC()
|
||||
m_SocketID(id),
|
||||
m_iSndKmKeyLen(0),
|
||||
m_iRcvKmKeyLen(0),
|
||||
m_SndKmState(SRT_KM_S_UNSECURED),
|
||||
m_RcvKmState(SRT_KM_S_UNSECURED),
|
||||
m_KmRefreshRatePkt(0),
|
||||
m_KmPreAnnouncePkt(0),
|
||||
m_bErrorReported(false)
|
||||
srt::CCryptoControl::CCryptoControl(SRTSOCKET id)
|
||||
: m_SocketID(id)
|
||||
, m_iSndKmKeyLen(0)
|
||||
, m_iRcvKmKeyLen(0)
|
||||
, m_SndKmState(SRT_KM_S_UNSECURED)
|
||||
, m_RcvKmState(SRT_KM_S_UNSECURED)
|
||||
, m_KmRefreshRatePkt(0)
|
||||
, m_KmPreAnnouncePkt(0)
|
||||
, m_iCryptoMode(CSrtConfig::CIPHER_MODE_AUTO)
|
||||
, m_bErrorReported(false)
|
||||
{
|
||||
|
||||
m_KmSecret.len = 0;
|
||||
//send
|
||||
m_SndKmLastTime = 0;
|
||||
m_SndKmMsg[0].MsgLen = 0;
|
||||
m_SndKmMsg[0].iPeerRetry = 0;
|
||||
m_SndKmMsg[1].MsgLen = 0;
|
||||
|
@ -565,45 +606,58 @@ m_bErrorReported(false)
|
|||
m_hRcvCrypto = NULL;
|
||||
}
|
||||
|
||||
bool CCryptoControl::init(HandshakeSide side, bool bidirectional SRT_ATR_UNUSED)
|
||||
bool srt::CCryptoControl::init(HandshakeSide side, const CSrtConfig& cfg, bool bidirectional SRT_ATR_UNUSED)
|
||||
{
|
||||
// NOTE: initiator creates m_hSndCrypto. When bidirectional,
|
||||
// it creates also m_hRcvCrypto with the same key length.
|
||||
// Acceptor creates nothing - it will create appropriate
|
||||
// contexts when receiving KMREQ from the initiator.
|
||||
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: HS SIDE:"
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: HS SIDE:"
|
||||
<< (side == HSD_INITIATOR ? "INITIATOR" : "RESPONDER")
|
||||
<< " DIRECTION:" << (bidirectional ? "BOTH" : (side == HSD_INITIATOR) ? "SENDER" : "RECEIVER"));
|
||||
|
||||
// Set UNSECURED state as default
|
||||
m_RcvKmState = SRT_KM_S_UNSECURED;
|
||||
m_iCryptoMode = cfg.iCryptoMode;
|
||||
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
if (!cfg.bTSBPD && m_iCryptoMode == CSrtConfig::CIPHER_MODE_AUTO)
|
||||
m_iCryptoMode = CSrtConfig::CIPHER_MODE_AES_CTR;
|
||||
const bool bUseGCM = m_iCryptoMode == CSrtConfig::CIPHER_MODE_AES_GCM;
|
||||
|
||||
if (bUseGCM && !isAESGCMSupported())
|
||||
{
|
||||
LOGC(cnlog.Warn, log << "CCryptoControl: AES GCM is not supported by the crypto service provider.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set security-pending state, if a password was set.
|
||||
m_SndKmState = hasPassphrase() ? SRT_KM_S_SECURING : SRT_KM_S_UNSECURED;
|
||||
|
||||
m_KmPreAnnouncePkt = m_parent->m_uKmPreAnnouncePkt;
|
||||
m_KmRefreshRatePkt = m_parent->m_uKmRefreshRatePkt;
|
||||
m_KmPreAnnouncePkt = cfg.uKmPreAnnouncePkt;
|
||||
m_KmRefreshRatePkt = cfg.uKmRefreshRatePkt;
|
||||
|
||||
if ( side == HSD_INITIATOR )
|
||||
if (side == HSD_INITIATOR)
|
||||
{
|
||||
if (hasPassphrase())
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
if (m_iSndKmKeyLen == 0)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: PBKEYLEN still 0, setting default 16");
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: PBKEYLEN still 0, setting default 16");
|
||||
m_iSndKmKeyLen = 16;
|
||||
}
|
||||
|
||||
bool ok = createCryptoCtx(Ref(m_hSndCrypto), m_iSndKmKeyLen, HAICRYPT_CRYPTO_DIR_TX);
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: creating SND crypto context: " << ok);
|
||||
bool ok = createCryptoCtx((m_hSndCrypto), m_iSndKmKeyLen, HAICRYPT_CRYPTO_DIR_TX, bUseGCM);
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: creating SND crypto context: " << ok);
|
||||
|
||||
if (ok && bidirectional)
|
||||
{
|
||||
m_iRcvKmKeyLen = m_iSndKmKeyLen;
|
||||
int st = HaiCrypt_Clone(m_hSndCrypto, HAICRYPT_CRYPTO_DIR_RX, &m_hRcvCrypto);
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: creating CLONED RCV crypto context: status=" << st);
|
||||
const int st = HaiCrypt_Clone(m_hSndCrypto, HAICRYPT_CRYPTO_DIR_RX, &m_hRcvCrypto);
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: creating CLONED RCV crypto context: status=" << st);
|
||||
ok = st == 0;
|
||||
}
|
||||
|
||||
|
@ -618,45 +672,54 @@ bool CCryptoControl::init(HandshakeSide side, bool bidirectional SRT_ATR_UNUSED)
|
|||
}
|
||||
|
||||
regenCryptoKm(
|
||||
false, // Do not send the key (will be attached it to the HSv5 handshake)
|
||||
bidirectional // replicate the key to the receiver context, if bidirectional
|
||||
);
|
||||
NULL, // Do not send the key (the KM msg will be attached to the HSv5 handshake)
|
||||
bidirectional // replicate the key to the receiver context, if bidirectional
|
||||
);
|
||||
|
||||
m_iCryptoMode = bUseGCM ? CSrtConfig::CIPHER_MODE_AES_GCM : CSrtConfig::CIPHER_MODE_AES_CTR;
|
||||
#else
|
||||
LOGC(mglog.Error, log << "CCryptoControl::init: encryption not supported");
|
||||
return true;
|
||||
// This error would be a consequence of setting the passphrase, while encryption
|
||||
// is turned off at compile time. Setting the password itself should be not allowed
|
||||
// so this could only happen as a consequence of an IPE.
|
||||
LOGC(cnlog.Error, log << "CCryptoControl::init: IPE: encryption not supported");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: CAN'T CREATE crypto: key length for SND = " << m_iSndKmKeyLen);
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: CAN'T CREATE crypto: key length for SND = " << m_iSndKmKeyLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "CCryptoControl::init: NOT creating crypto contexts - will be created upon reception of KMREQ");
|
||||
HLOGC(cnlog.Debug, log << "CCryptoControl::init: NOT creating crypto contexts - will be created upon reception of KMREQ");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCryptoControl::close()
|
||||
void srt::CCryptoControl::close()
|
||||
{
|
||||
/* Wipeout secrets */
|
||||
sync::ScopedLock lck(m_mtxLock);
|
||||
memset(&m_KmSecret, 0, sizeof(m_KmSecret));
|
||||
}
|
||||
|
||||
std::string CCryptoControl::CONID() const
|
||||
std::string srt::CCryptoControl::CONID() const
|
||||
{
|
||||
if ( m_SocketID == 0 )
|
||||
if (m_SocketID == 0)
|
||||
return "";
|
||||
|
||||
std::ostringstream os;
|
||||
os << "%" << m_SocketID << ":";
|
||||
os << "@" << m_SocketID << ":";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
namespace srt {
|
||||
static std::string CryptoFlags(int flg)
|
||||
{
|
||||
using namespace std;
|
||||
|
@ -673,13 +736,12 @@ static std::string CryptoFlags(int flg)
|
|||
copy(f.begin(), f.end(), ostream_iterator<string>(os, "|"));
|
||||
return os.str();
|
||||
}
|
||||
#endif
|
||||
} // namespace srt
|
||||
#endif // ENABLE_HEAVY_LOGGING
|
||||
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
bool CCryptoControl::createCryptoCtx(ref_t<HaiCrypt_Handle> hCrypto, size_t keylen, HaiCrypt_CryptoDir cdir)
|
||||
bool srt::CCryptoControl::createCryptoCtx(HaiCrypt_Handle& w_hCrypto, size_t keylen, HaiCrypt_CryptoDir cdir, bool bAESGCM)
|
||||
{
|
||||
|
||||
if (*hCrypto)
|
||||
if (w_hCrypto)
|
||||
{
|
||||
// XXX You can check here if the existing handle represents
|
||||
// a correctly defined crypto. But this doesn't seem to be
|
||||
|
@ -690,7 +752,7 @@ bool CCryptoControl::createCryptoCtx(ref_t<HaiCrypt_Handle> hCrypto, size_t keyl
|
|||
|
||||
if ((m_KmSecret.len <= 0) || (keylen <= 0))
|
||||
{
|
||||
LOGC(mglog.Error, log << CONID() << "cryptoCtx: missing secret (" << m_KmSecret.len << ") or key length (" << keylen << ")");
|
||||
LOGC(cnlog.Error, log << CONID() << "cryptoCtx: IPE missing secret (" << m_KmSecret.len << ") or key length (" << keylen << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -700,7 +762,7 @@ bool CCryptoControl::createCryptoCtx(ref_t<HaiCrypt_Handle> hCrypto, size_t keyl
|
|||
m_KmRefreshRatePkt = 2000;
|
||||
m_KmPreAnnouncePkt = 500;
|
||||
#endif
|
||||
crypto_cfg.flags = HAICRYPT_CFG_F_CRYPTO | (cdir == HAICRYPT_CRYPTO_DIR_TX ? HAICRYPT_CFG_F_TX : 0);
|
||||
crypto_cfg.flags = HAICRYPT_CFG_F_CRYPTO | (cdir == HAICRYPT_CRYPTO_DIR_TX ? HAICRYPT_CFG_F_TX : 0) | (bAESGCM ? HAICRYPT_CFG_F_GCM : 0);
|
||||
crypto_cfg.xport = HAICRYPT_XPT_SRT;
|
||||
crypto_cfg.cryspr = HaiCryptCryspr_Get_Instance();
|
||||
crypto_cfg.key_len = (size_t)keylen;
|
||||
|
@ -709,38 +771,38 @@ bool CCryptoControl::createCryptoCtx(ref_t<HaiCrypt_Handle> hCrypto, size_t keyl
|
|||
crypto_cfg.km_refresh_rate_pkt = m_KmRefreshRatePkt == 0 ? HAICRYPT_DEF_KM_REFRESH_RATE : m_KmRefreshRatePkt;
|
||||
crypto_cfg.km_pre_announce_pkt = m_KmPreAnnouncePkt == 0 ? SRT_CRYPT_KM_PRE_ANNOUNCE : m_KmPreAnnouncePkt;
|
||||
crypto_cfg.secret = m_KmSecret;
|
||||
//memcpy(&crypto_cfg.secret, &m_KmSecret, sizeof(crypto_cfg.secret));
|
||||
|
||||
HLOGC(mglog.Debug, log << "CRYPTO CFG: flags=" << CryptoFlags(crypto_cfg.flags) << " xport=" << crypto_cfg.xport << " cryspr=" << crypto_cfg.cryspr
|
||||
HLOGC(cnlog.Debug, log << "CRYPTO CFG: flags=" << CryptoFlags(crypto_cfg.flags) << " xport=" << crypto_cfg.xport << " cryspr=" << crypto_cfg.cryspr
|
||||
<< " keylen=" << crypto_cfg.key_len << " passphrase_length=" << crypto_cfg.secret.len);
|
||||
|
||||
if (HaiCrypt_Create(&crypto_cfg, &hCrypto.get()) != HAICRYPT_OK)
|
||||
if (HaiCrypt_Create(&crypto_cfg, (&w_hCrypto)) != HAICRYPT_OK)
|
||||
{
|
||||
LOGC(mglog.Error, log << CONID() << "cryptoCtx: could not create " << (cdir == HAICRYPT_CRYPTO_DIR_TX ? "tx" : "rx") << " crypto ctx");
|
||||
LOGC(cnlog.Error, log << CONID() << "cryptoCtx: could not create " << (cdir == HAICRYPT_CRYPTO_DIR_TX ? "tx" : "rx") << " crypto ctx");
|
||||
return false;
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << CONID() << "cryptoCtx: CREATED crypto for dir=" << (cdir == HAICRYPT_CRYPTO_DIR_TX ? "tx" : "rx") << " keylen=" << keylen);
|
||||
HLOGC(cnlog.Debug, log << CONID() << "cryptoCtx: CREATED crypto for dir=" << (cdir == HAICRYPT_CRYPTO_DIR_TX ? "tx" : "rx") << " keylen=" << keylen);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool CCryptoControl::createCryptoCtx(ref_t<HaiCrypt_Handle>, size_t, HaiCrypt_CryptoDir)
|
||||
bool srt::CCryptoControl::createCryptoCtx(HaiCrypt_Handle&, size_t, HaiCrypt_CryptoDir, bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif // SRT_ENABLE_ENCRYPTION
|
||||
|
||||
|
||||
EncryptionStatus CCryptoControl::encrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
||||
srt::EncryptionStatus srt::CCryptoControl::encrypt(CPacket& w_packet SRT_ATR_UNUSED)
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
// Encryption not enabled - do nothing.
|
||||
if ( getSndCryptoFlags() == EK_NOENC )
|
||||
return ENCS_CLEAR;
|
||||
|
||||
CPacket& packet = *r_packet;
|
||||
int rc = HaiCrypt_Tx_Data(m_hSndCrypto, (uint8_t*)packet.getHeader(), (uint8_t*)packet.m_pcData, packet.getLength());
|
||||
// Note that in case of GCM the header has to zero Retransmitted Packet Flag (R).
|
||||
// If TSBPD is disabled, timestamp also has to be zeroed.
|
||||
int rc = HaiCrypt_Tx_Data(m_hSndCrypto, ((uint8_t*)w_packet.getHeader()), ((uint8_t*)w_packet.m_pcData), w_packet.getLength());
|
||||
if (rc < 0)
|
||||
{
|
||||
return ENCS_FAILED;
|
||||
|
@ -749,7 +811,7 @@ EncryptionStatus CCryptoControl::encrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
{
|
||||
// XXX what happens if the encryption is said to be "succeeded",
|
||||
// but the length is 0? Shouldn't this be treated as unwanted?
|
||||
packet.setLength(rc);
|
||||
w_packet.setLength(rc);
|
||||
}
|
||||
|
||||
return ENCS_CLEAR;
|
||||
|
@ -758,14 +820,12 @@ EncryptionStatus CCryptoControl::encrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
#endif
|
||||
}
|
||||
|
||||
EncryptionStatus CCryptoControl::decrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
||||
srt::EncryptionStatus srt::CCryptoControl::decrypt(CPacket& w_packet SRT_ATR_UNUSED)
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
CPacket& packet = *r_packet;
|
||||
|
||||
if (packet.getMsgCryptoFlags() == EK_NOENC)
|
||||
if (w_packet.getMsgCryptoFlags() == EK_NOENC)
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "CPacket::decrypt: packet not encrypted");
|
||||
HLOGC(cnlog.Debug, log << "CPacket::decrypt: packet not encrypted");
|
||||
return ENCS_CLEAR; // not encrypted, no need do decrypt, no flags to be modified
|
||||
}
|
||||
|
||||
|
@ -776,8 +836,8 @@ EncryptionStatus CCryptoControl::decrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
// We were unaware that the peer has set password,
|
||||
// but now here we are.
|
||||
m_RcvKmState = SRT_KM_S_SECURING;
|
||||
LOGC(mglog.Note, log << "SECURITY UPDATE: Peer has surprised Agent with encryption, but KMX is pending - current packet size="
|
||||
<< packet.getLength() << " dropped");
|
||||
LOGC(cnlog.Note, log << "SECURITY UPDATE: Peer has surprised Agent with encryption, but KMX is pending - current packet size="
|
||||
<< w_packet.getLength() << " dropped");
|
||||
return ENCS_FAILED;
|
||||
}
|
||||
else
|
||||
|
@ -786,7 +846,7 @@ EncryptionStatus CCryptoControl::decrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
// which means that it will be unable to decrypt
|
||||
// sent payloads anyway.
|
||||
m_RcvKmState = SRT_KM_S_NOSECRET;
|
||||
LOGP(mglog.Error, "SECURITY FAILURE: Agent has no PW, but Peer sender has declared one, can't decrypt");
|
||||
LOGP(cnlog.Warn, "SECURITY FAILURE: Agent has no PW, but Peer sender has declared one, can't decrypt");
|
||||
// This only informs about the state change; it will be also caught by the condition below
|
||||
}
|
||||
}
|
||||
|
@ -807,28 +867,28 @@ EncryptionStatus CCryptoControl::decrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
if (!m_bErrorReported)
|
||||
{
|
||||
m_bErrorReported = true;
|
||||
LOGC(mglog.Error, log << "SECURITY STATUS: " << KmStateStr(m_RcvKmState) << " - can't decrypt packet.");
|
||||
LOGC(cnlog.Error, log << "SECURITY STATUS: " << KmStateStr(m_RcvKmState) << " - can't decrypt w_packet.");
|
||||
}
|
||||
HLOGC(mglog.Debug, log << "Packet still not decrypted, status=" << KmStateStr(m_RcvKmState)
|
||||
<< " - dropping size=" << packet.getLength());
|
||||
HLOGC(cnlog.Debug, log << "Packet still not decrypted, status=" << KmStateStr(m_RcvKmState)
|
||||
<< " - dropping size=" << w_packet.getLength());
|
||||
return ENCS_FAILED;
|
||||
}
|
||||
|
||||
int rc = HaiCrypt_Rx_Data(m_hRcvCrypto, (uint8_t *)packet.getHeader(), (uint8_t *)packet.m_pcData, packet.getLength());
|
||||
if ( rc <= 0 )
|
||||
const int rc = HaiCrypt_Rx_Data(m_hRcvCrypto, ((uint8_t *)w_packet.getHeader()), ((uint8_t *)w_packet.m_pcData), w_packet.getLength());
|
||||
if (rc <= 0)
|
||||
{
|
||||
LOGC(mglog.Error, log << "decrypt ERROR (IPE): HaiCrypt_Rx_Data failure=" << rc << " - returning failed decryption");
|
||||
LOGC(cnlog.Note, log << "decrypt ERROR: HaiCrypt_Rx_Data failure=" << rc << " - returning failed decryption");
|
||||
// -1: decryption failure
|
||||
// 0: key not received yet
|
||||
return ENCS_FAILED;
|
||||
}
|
||||
// Otherwise: rc == decrypted text length.
|
||||
packet.setLength(rc); /* In case clr txt size is different from cipher txt */
|
||||
w_packet.setLength(rc); /* In case clr txt size is different from cipher txt */
|
||||
|
||||
// Decryption succeeded. Update flags.
|
||||
packet.setMsgCryptoFlags(EK_NOENC);
|
||||
w_packet.setMsgCryptoFlags(EK_NOENC);
|
||||
|
||||
HLOGC(mglog.Debug, log << "decrypt: successfully decrypted, resulting length=" << rc);
|
||||
HLOGC(cnlog.Debug, log << "decrypt: successfully decrypted, resulting length=" << rc);
|
||||
return ENCS_CLEAR;
|
||||
#else
|
||||
return ENCS_NOTSUP;
|
||||
|
@ -836,9 +896,10 @@ EncryptionStatus CCryptoControl::decrypt(ref_t<CPacket> r_packet SRT_ATR_UNUSED)
|
|||
}
|
||||
|
||||
|
||||
CCryptoControl::~CCryptoControl()
|
||||
srt::CCryptoControl::~CCryptoControl()
|
||||
{
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
close();
|
||||
if (m_hSndCrypto)
|
||||
{
|
||||
HaiCrypt_Close(m_hSndCrypto);
|
||||
|
@ -850,38 +911,3 @@ CCryptoControl::~CCryptoControl()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
std::string SrtFlagString(int32_t flags)
|
||||
{
|
||||
#define LEN(arr) (sizeof (arr)/(sizeof ((arr)[0])))
|
||||
|
||||
std::string output;
|
||||
static std::string namera[] = { "TSBPD-snd", "TSBPD-rcv", "haicrypt", "TLPktDrop", "NAKReport", "ReXmitFlag", "StreamAPI" };
|
||||
|
||||
size_t i = 0;
|
||||
for ( ; i < LEN(namera); ++i )
|
||||
{
|
||||
if ( (flags & 1) == 1 )
|
||||
{
|
||||
output += "+" + namera[i] + " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
output += "-" + namera[i] + " ";
|
||||
}
|
||||
|
||||
flags >>= 1;
|
||||
//if ( flags == 0 )
|
||||
// break;
|
||||
}
|
||||
|
||||
#undef LEN
|
||||
|
||||
if ( flags != 0 )
|
||||
{
|
||||
output += "+unknown";
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
89
trunk/3rdparty/srt-1-fit/srtcore/crypto.h
vendored
89
trunk/3rdparty/srt-1-fit/srtcore/crypto.h
vendored
|
@ -13,8 +13,8 @@ written by
|
|||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef INC__CRYPTO_H
|
||||
#define INC__CRYPTO_H
|
||||
#ifndef INC_SRT_CRYPTO_H
|
||||
#define INC_SRT_CRYPTO_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
@ -28,33 +28,34 @@ written by
|
|||
#include <haicrypt.h>
|
||||
#include <hcrypt_msg.h>
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
|
||||
std::string KmStateStr(SRT_KM_STATE state);
|
||||
|
||||
namespace srt_logging
|
||||
{
|
||||
extern Logger mglog;
|
||||
std::string KmStateStr(SRT_KM_STATE state);
|
||||
#if ENABLE_LOGGING
|
||||
extern Logger cnlog;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
namespace srt
|
||||
{
|
||||
class CUDT;
|
||||
struct CSrtConfig;
|
||||
|
||||
|
||||
// For KMREQ/KMRSP. Only one field is used.
|
||||
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(int32_t);
|
||||
|
||||
enum Whether2RegenKm {DONT_REGEN_KM = 0, REGEN_KM = 1};
|
||||
const size_t SRTDATA_MAXSIZE = SRT_CMD_MAXSZ/sizeof(uint32_t);
|
||||
|
||||
class CCryptoControl
|
||||
{
|
||||
//public:
|
||||
class CUDT* m_parent;
|
||||
SRTSOCKET m_SocketID;
|
||||
SRTSOCKET m_SocketID;
|
||||
|
||||
size_t m_iSndKmKeyLen; //Key length
|
||||
size_t m_iRcvKmKeyLen; //Key length from rx KM
|
||||
size_t m_iSndKmKeyLen; //Key length
|
||||
size_t m_iRcvKmKeyLen; //Key length from rx KM
|
||||
|
||||
// Temporarily allow these to be accessed.
|
||||
public:
|
||||
|
@ -66,10 +67,12 @@ private:
|
|||
// 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
|
||||
uint64_t m_SndKmLastTime;
|
||||
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;
|
||||
|
@ -82,6 +85,9 @@ private:
|
|||
bool m_bErrorReported;
|
||||
|
||||
public:
|
||||
static void globalInit();
|
||||
|
||||
static bool isAESGCMSupported();
|
||||
|
||||
bool sendingAllowed()
|
||||
{
|
||||
|
@ -105,13 +111,16 @@ public:
|
|||
return m_KmSecret.len > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int getCryptoMode() const
|
||||
{
|
||||
return m_iCryptoMode;
|
||||
}
|
||||
|
||||
#ifdef SRT_ENABLE_ENCRYPTION
|
||||
void regenCryptoKm(bool sendit, bool bidirectional);
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// 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);
|
||||
|
||||
size_t KeyLen() { return m_iSndKmKeyLen; }
|
||||
|
||||
|
@ -119,7 +128,8 @@ public:
|
|||
void updateKmState(int cmd, size_t srtlen);
|
||||
|
||||
// Detailed processing
|
||||
int processSrtMsg_KMREQ(const uint32_t* srtdata, size_t len, uint32_t* srtdata_out, ref_t<size_t> r_srtlen, int hsv);
|
||||
int processSrtMsg_KMREQ(const uint32_t* srtdata, size_t len, int hsv,
|
||||
uint32_t srtdata_out[], size_t&);
|
||||
|
||||
// This returns:
|
||||
// 1 - the given payload is the same as the currently used key
|
||||
|
@ -158,18 +168,18 @@ public:
|
|||
void getKmMsg_markSent(size_t ki, bool runtime)
|
||||
{
|
||||
#if ENABLE_LOGGING
|
||||
using srt_logging::mglog;
|
||||
using srt_logging::cnlog;
|
||||
#endif
|
||||
|
||||
m_SndKmLastTime = CTimer::getTime();
|
||||
m_SndKmLastTime = sync::steady_clock::now();
|
||||
if (runtime)
|
||||
{
|
||||
m_SndKmMsg[ki].iPeerRetry--;
|
||||
HLOGC(mglog.Debug, log << "getKmMsg_markSent: key[" << ki << "]: len=" << m_SndKmMsg[ki].MsgLen << " retry=" << m_SndKmMsg[ki].iPeerRetry);
|
||||
HLOGC(cnlog.Debug, log << "getKmMsg_markSent: key[" << ki << "]: len=" << m_SndKmMsg[ki].MsgLen << " retry=" << m_SndKmMsg[ki].iPeerRetry);
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(mglog.Debug, log << "getKmMsg_markSent: key[" << ki << "]: len=" << m_SndKmMsg[ki].MsgLen << " STILL IN USE.");
|
||||
HLOGC(cnlog.Debug, log << "getKmMsg_markSent: key[" << ki << "]: len=" << m_SndKmMsg[ki].MsgLen << " STILL IN USE.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,25 +201,28 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
CCryptoControl(CUDT* parent, SRTSOCKET id);
|
||||
CCryptoControl(SRTSOCKET id);
|
||||
|
||||
// DEBUG PURPOSES:
|
||||
std::string CONID() const;
|
||||
std::string FormatKmMessage(std::string hdr, int cmd, size_t srtlen);
|
||||
|
||||
bool init(HandshakeSide, bool);
|
||||
bool init(HandshakeSide, const CSrtConfig&, bool);
|
||||
SRT_ATTR_EXCLUDES(m_mtxLock)
|
||||
void close();
|
||||
|
||||
// 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(Whether2RegenKm regen);
|
||||
|
||||
/// (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).
|
||||
/// - 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)
|
||||
{
|
||||
m_KmSecret = secret;
|
||||
//memcpy(&m_KmSecret, &secret, sizeof(m_KmSecret));
|
||||
}
|
||||
|
||||
void setCryptoKeylen(size_t keylen)
|
||||
|
@ -218,7 +231,7 @@ public:
|
|||
m_iRcvKmKeyLen = keylen;
|
||||
}
|
||||
|
||||
bool createCryptoCtx(ref_t<HaiCrypt_Handle> rh, size_t keylen, HaiCrypt_CryptoDir tx);
|
||||
bool createCryptoCtx(HaiCrypt_Handle& rh, size_t keylen, HaiCrypt_CryptoDir tx, bool bAESGCM);
|
||||
|
||||
int getSndCryptoFlags() const
|
||||
{
|
||||
|
@ -253,16 +266,18 @@ public:
|
|||
/// the encryption will fail.
|
||||
/// XXX Encryption flags in the PH_MSGNO
|
||||
/// field in the header must be correctly set before calling.
|
||||
EncryptionStatus encrypt(ref_t<CPacket> r_packet);
|
||||
EncryptionStatus encrypt(CPacket& w_packet);
|
||||
|
||||
/// Decrypts the packet. If the packet has ENCKEYSPEC part
|
||||
/// in PH_MSGNO set to EK_NOENC, it does nothing. It decrypts
|
||||
/// only if the encryption correctly configured, otherwise it
|
||||
/// fails. After successful decryption, the ENCKEYSPEC part
|
||||
// in PH_MSGNO is set to EK_NOENC.
|
||||
EncryptionStatus decrypt(ref_t<CPacket> r_packet);
|
||||
EncryptionStatus decrypt(CPacket& w_packet);
|
||||
|
||||
~CCryptoControl();
|
||||
};
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif // SRT_CONGESTION_CONTROL_H
|
||||
|
|
474
trunk/3rdparty/srt-1-fit/srtcore/epoll.cpp
vendored
474
trunk/3rdparty/srt-1-fit/srtcore/epoll.cpp
vendored
|
@ -50,37 +50,36 @@ modified by
|
|||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef LINUX
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if __APPLE__
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
#if defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#define SRT_IMPORT_EVENT
|
||||
#include "platform_sys.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
#if defined(__FreeBSD_kernel__)
|
||||
#include <sys/event.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "epoll.h"
|
||||
#include "logging.h"
|
||||
#include "udt.h"
|
||||
#include "utilities.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace srt::sync;
|
||||
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
namespace srt {
|
||||
static ostream& PrintEpollEvent(ostream& os, int events, int et_events = 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace srt_logging
|
||||
{
|
||||
extern Logger mglog;
|
||||
extern Logger eilog, ealog;
|
||||
}
|
||||
|
||||
using namespace srt_logging;
|
||||
|
@ -89,20 +88,21 @@ using namespace srt_logging;
|
|||
#define IF_DIRNAME(tested, flag, name) (tested & flag ? name : "")
|
||||
#endif
|
||||
|
||||
CEPoll::CEPoll():
|
||||
srt::CEPoll::CEPoll():
|
||||
m_iIDSeed(0)
|
||||
{
|
||||
CGuard::createMutex(m_EPollLock);
|
||||
// Exception -> CUDTUnited ctor.
|
||||
setupMutex(m_EPollLock, "EPoll");
|
||||
}
|
||||
|
||||
CEPoll::~CEPoll()
|
||||
srt::CEPoll::~CEPoll()
|
||||
{
|
||||
CGuard::releaseMutex(m_EPollLock);
|
||||
releaseMutex(m_EPollLock);
|
||||
}
|
||||
|
||||
int CEPoll::create()
|
||||
int srt::CEPoll::create(CEPollDesc** pout)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
|
||||
if (++ m_iIDSeed >= 0x7FFFFFFF)
|
||||
m_iIDSeed = 0;
|
||||
|
@ -114,7 +114,31 @@ int CEPoll::create()
|
|||
int localid = 0;
|
||||
|
||||
#ifdef LINUX
|
||||
localid = epoll_create(1024);
|
||||
|
||||
// NOTE: epoll_create1() and EPOLL_CLOEXEC were introduced in GLIBC-2.9.
|
||||
// So earlier versions of GLIBC, must use epoll_create() and set
|
||||
// FD_CLOEXEC on the file descriptor returned by it after the fact.
|
||||
#if defined(EPOLL_CLOEXEC)
|
||||
int flags = 0;
|
||||
#if ENABLE_SOCK_CLOEXEC
|
||||
flags |= EPOLL_CLOEXEC;
|
||||
#endif
|
||||
localid = epoll_create1(flags);
|
||||
#else
|
||||
localid = epoll_create(1);
|
||||
#if ENABLE_SOCK_CLOEXEC
|
||||
if (localid != -1)
|
||||
{
|
||||
int fdFlags = fcntl(localid, F_GETFD);
|
||||
if (fdFlags != -1)
|
||||
{
|
||||
fdFlags |= FD_CLOEXEC;
|
||||
fcntl(localid, F_SETFD, fdFlags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Possible reasons of -1 error:
|
||||
EMFILE: The per-user limit on the number of epoll instances imposed by /proc/sys/fs/epoll/max_user_instances was encountered.
|
||||
ENFILE: The system limit on the total number of open files has been reached.
|
||||
|
@ -122,25 +146,82 @@ ENOMEM: There was insufficient memory to create the kernel object.
|
|||
*/
|
||||
if (localid < 0)
|
||||
throw CUDTException(MJ_SETUP, MN_NONE, errno);
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
localid = kqueue();
|
||||
if (localid < 0)
|
||||
throw CUDTException(MJ_SETUP, MN_NONE, errno);
|
||||
#else
|
||||
// on Solaris, use /dev/poll
|
||||
// TODO: Solaris, use port_getn()
|
||||
// https://docs.oracle.com/cd/E86824_01/html/E54766/port-get-3c.html
|
||||
// on Windows, select
|
||||
#endif
|
||||
|
||||
pair<map<int, CEPollDesc>::iterator, bool> res = m_mPolls.insert(make_pair(m_iIDSeed, CEPollDesc(m_iIDSeed, localid)));
|
||||
if (!res.second) // Insertion failed (no memory?)
|
||||
throw CUDTException(MJ_SETUP, MN_NONE);
|
||||
if (pout)
|
||||
*pout = &res.first->second;
|
||||
|
||||
return m_iIDSeed;
|
||||
}
|
||||
|
||||
int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
||||
int srt::CEPoll::clear_usocks(int eid)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
// This should remove all SRT sockets from given eid.
|
||||
ScopedLock pg (m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(MJ_NOTSUP, MN_EIDINVAL);
|
||||
|
||||
CEPollDesc& d = p->second;
|
||||
|
||||
d.clearAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void srt::CEPoll::clear_ready_usocks(CEPollDesc& d, int direction)
|
||||
{
|
||||
if ((direction & ~SRT_EPOLL_EVENTTYPES) != 0)
|
||||
{
|
||||
// This is internal function, so simply report an IPE on incorrect usage.
|
||||
LOGC(eilog.Error, log << "CEPoll::clear_ready_usocks: IPE, event flags exceed event types: " << direction);
|
||||
return;
|
||||
}
|
||||
ScopedLock pg (m_EPollLock);
|
||||
|
||||
vector<SRTSOCKET> cleared;
|
||||
|
||||
CEPollDesc::enotice_t::iterator i = d.enotice_begin();
|
||||
while (i != d.enotice_end())
|
||||
{
|
||||
IF_HEAVY_LOGGING(SRTSOCKET subsock = i->fd);
|
||||
SRTSOCKET rs = d.clearEventSub(i++, direction);
|
||||
// This function returns:
|
||||
// - a valid socket - if there are no other subscription after 'direction' was cleared
|
||||
// - SRT_INVALID_SOCK otherwise
|
||||
// Valid sockets should be collected as sockets that no longer
|
||||
// have a subscribed event should be deleted from subscriptions.
|
||||
if (rs != SRT_INVALID_SOCK)
|
||||
{
|
||||
HLOGC(eilog.Debug, log << "CEPoll::clear_ready_usocks: @" << rs << " got all subscription cleared");
|
||||
cleared.push_back(rs);
|
||||
}
|
||||
else
|
||||
{
|
||||
HLOGC(eilog.Debug, log << "CEPoll::clear_ready_usocks: @" << subsock << " is still subscribed");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < cleared.size(); ++j)
|
||||
d.removeSubscription(cleared[j]);
|
||||
}
|
||||
|
||||
int srt::CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
||||
{
|
||||
ScopedLock pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
|
@ -155,18 +236,18 @@ int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
else
|
||||
{
|
||||
ev.events = 0;
|
||||
if (*events & UDT_EPOLL_IN)
|
||||
if (*events & SRT_EPOLL_IN)
|
||||
ev.events |= EPOLLIN;
|
||||
if (*events & UDT_EPOLL_OUT)
|
||||
if (*events & SRT_EPOLL_OUT)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (*events & UDT_EPOLL_ERR)
|
||||
if (*events & SRT_EPOLL_ERR)
|
||||
ev.events |= EPOLLERR;
|
||||
}
|
||||
|
||||
ev.data.fd = s;
|
||||
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_ADD, s, &ev) < 0)
|
||||
throw CUDTException();
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
struct kevent ke[2];
|
||||
int num = 0;
|
||||
|
||||
|
@ -177,11 +258,11 @@ int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (*events & UDT_EPOLL_IN)
|
||||
if (*events & SRT_EPOLL_IN)
|
||||
{
|
||||
EV_SET(&ke[num++], s, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
}
|
||||
if (*events & UDT_EPOLL_OUT)
|
||||
if (*events & SRT_EPOLL_OUT)
|
||||
{
|
||||
EV_SET(&ke[num++], s, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
}
|
||||
|
@ -190,6 +271,10 @@ int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
throw CUDTException();
|
||||
#else
|
||||
|
||||
// fake use 'events' to prevent warning. Remove when implemented.
|
||||
(void)events;
|
||||
(void)s;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Microsoft Visual Studio doesn't support the #warning directive - nonstandard anyway.
|
||||
// Use #pragma message with the same text.
|
||||
|
@ -206,9 +291,9 @@ int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
|
||||
int srt::CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
|
@ -218,7 +303,7 @@ int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
|
|||
epoll_event ev; // ev is ignored, for compatibility with old Linux kernel only.
|
||||
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_DEL, s, &ev) < 0)
|
||||
throw CUDTException();
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
struct kevent ke;
|
||||
|
||||
//
|
||||
|
@ -237,9 +322,10 @@ int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
|
|||
}
|
||||
|
||||
// Need this to atomically modify polled events (ex: remove write/keep read)
|
||||
int CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
||||
int srt::CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
IF_HEAVY_LOGGING(ostringstream evd);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
|
@ -250,9 +336,12 @@ int CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
|||
int32_t evts = events ? *events : uint32_t(SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR);
|
||||
bool edgeTriggered = evts & SRT_EPOLL_ET;
|
||||
evts &= ~SRT_EPOLL_ET;
|
||||
|
||||
// et_evts = all events, if SRT_EPOLL_ET, or only those that are always ET otherwise.
|
||||
int32_t et_evts = edgeTriggered ? evts : evts & SRT_EPOLL_ETONLY;
|
||||
if (evts)
|
||||
{
|
||||
pair<CEPollDesc::ewatch_t::iterator, bool> iter_new = d.addWatch(u, evts, edgeTriggered);
|
||||
pair<CEPollDesc::ewatch_t::iterator, bool> iter_new = d.addWatch(u, evts, et_evts);
|
||||
CEPollDesc::Wait& wait = iter_new.first->second;
|
||||
if (!iter_new.second)
|
||||
{
|
||||
|
@ -260,6 +349,7 @@ int CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
|||
// parameter, but others are probably unchanged. Change them
|
||||
// forcefully and take out notices that are no longer valid.
|
||||
const int removable = wait.watch & ~evts;
|
||||
IF_HEAVY_LOGGING(PrintEpollEvent(evd, evts & (~wait.watch)));
|
||||
|
||||
// Check if there are any events that would be removed.
|
||||
// If there are no removed events watched (for example, when
|
||||
|
@ -272,11 +362,16 @@ int CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
|||
|
||||
// Update the watch configuration, including edge
|
||||
wait.watch = evts;
|
||||
if (edgeTriggered)
|
||||
wait.edge = evts;
|
||||
wait.edge = et_evts;
|
||||
|
||||
// Now it should look exactly like newly added
|
||||
// and the state is also updated
|
||||
HLOGC(ealog.Debug, log << "srt_epoll_update_usock: UPDATED E" << eid << " for @" << u << " +" << evd.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
IF_HEAVY_LOGGING(PrintEpollEvent(evd, evts));
|
||||
HLOGC(ealog.Debug, log << "srt_epoll_update_usock: ADDED E" << eid << " for @" << u << " " << evd.str());
|
||||
}
|
||||
|
||||
const int newstate = wait.watch & wait.state;
|
||||
|
@ -287,20 +382,21 @@ int CEPoll::update_usock(const int eid, const SRTSOCKET& u, const int* events)
|
|||
}
|
||||
else if (edgeTriggered)
|
||||
{
|
||||
// Specified only SRT_EPOLL_ET flag, but no event flag. Error.
|
||||
LOGC(ealog.Error, log << "srt_epoll_update_usock: Specified only SRT_EPOLL_ET flag, but no event flag. Error.");
|
||||
throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update with no events means to remove subscription
|
||||
HLOGC(ealog.Debug, log << "srt_epoll_update_usock: REMOVED E" << eid << " socket @" << u);
|
||||
d.removeSubscription(u);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::update_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
||||
int srt::CEPoll::update_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
|
@ -315,18 +411,18 @@ int CEPoll::update_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
else
|
||||
{
|
||||
ev.events = 0;
|
||||
if (*events & UDT_EPOLL_IN)
|
||||
if (*events & SRT_EPOLL_IN)
|
||||
ev.events |= EPOLLIN;
|
||||
if (*events & UDT_EPOLL_OUT)
|
||||
if (*events & SRT_EPOLL_OUT)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (*events & UDT_EPOLL_ERR)
|
||||
if (*events & SRT_EPOLL_ERR)
|
||||
ev.events |= EPOLLERR;
|
||||
}
|
||||
|
||||
ev.data.fd = s;
|
||||
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_MOD, s, &ev) < 0)
|
||||
throw CUDTException();
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
struct kevent ke[2];
|
||||
int num = 0;
|
||||
|
||||
|
@ -345,17 +441,23 @@ int CEPoll::update_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (*events & UDT_EPOLL_IN)
|
||||
if (*events & SRT_EPOLL_IN)
|
||||
{
|
||||
EV_SET(&ke[num++], s, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
}
|
||||
if (*events & UDT_EPOLL_OUT)
|
||||
if (*events & SRT_EPOLL_OUT)
|
||||
{
|
||||
EV_SET(&ke[num++], s, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
}
|
||||
}
|
||||
if (kevent(p->second.m_iLocalID, ke, num, NULL, 0, NULL) < 0)
|
||||
throw CUDTException();
|
||||
#else
|
||||
|
||||
// fake use 'events' to prevent warning. Remove when implemented.
|
||||
(void)events;
|
||||
(void)s;
|
||||
|
||||
#endif
|
||||
// Assuming add is used if not inserted
|
||||
// p->second.m_sLocals.insert(s);
|
||||
|
@ -363,9 +465,9 @@ int CEPoll::update_ssock(const int eid, const SYSSOCKET& s, const int* events)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::setflags(const int eid, int32_t flags)
|
||||
int srt::CEPoll::setflags(const int eid, int32_t flags)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(MJ_NOTSUP, MN_EIDINVAL);
|
||||
|
@ -388,7 +490,7 @@ int CEPoll::setflags(const int eid, int32_t flags)
|
|||
return oflags;
|
||||
}
|
||||
|
||||
int CEPoll::uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut)
|
||||
int srt::CEPoll::uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut)
|
||||
{
|
||||
// It is allowed to call this function witn fdsSize == 0
|
||||
// and therefore also NULL fdsSet. This will then only report
|
||||
|
@ -396,12 +498,12 @@ int CEPoll::uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t m
|
|||
if (fdsSize < 0 || (fdsSize > 0 && !fdsSet))
|
||||
throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
|
||||
int64_t entertime = CTimer::getTime();
|
||||
steady_clock::time_point entertime = steady_clock::now();
|
||||
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
ScopedLock pg(m_EPollLock);
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
throw CUDTException(MJ_NOTSUP, MN_EIDINVAL);
|
||||
|
@ -410,7 +512,7 @@ int CEPoll::uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t m
|
|||
if (!ed.flags(SRT_EPOLL_ENABLE_EMPTY) && ed.watch_empty())
|
||||
{
|
||||
// Empty EID is not allowed, report error.
|
||||
throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
throw CUDTException(MJ_NOTSUP, MN_EEMPTY);
|
||||
}
|
||||
|
||||
if (ed.flags(SRT_EPOLL_ENABLE_OUTPUTCHECK) && (fdsSet == NULL || fdsSize == 0))
|
||||
|
@ -444,16 +546,16 @@ int CEPoll::uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t m
|
|||
return total;
|
||||
}
|
||||
|
||||
if ((msTimeOut >= 0) && (int64_t(CTimer::getTime() - entertime) >= msTimeOut * int64_t(1000)))
|
||||
if ((msTimeOut >= 0) && (count_microseconds(srt::sync::steady_clock::now() - entertime) >= msTimeOut * int64_t(1000)))
|
||||
break; // official wait does: throw CUDTException(MJ_AGAIN, MN_XMTIMEOUT, 0);
|
||||
|
||||
CTimer::waitForEvent();
|
||||
CGlobEvent::waitForEvent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds)
|
||||
int srt::CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds)
|
||||
{
|
||||
// if all fields is NULL and waiting time is infinite, then this would be a deadlock
|
||||
if (!readfds && !writefds && !lrfds && !lwfds && (msTimeOut < 0))
|
||||
|
@ -467,18 +569,16 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
|
||||
int total = 0;
|
||||
|
||||
int64_t entertime = CTimer::getTime();
|
||||
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: START for eid=" << eid);
|
||||
|
||||
srt::sync::steady_clock::time_point entertime = srt::sync::steady_clock::now();
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
CGuard epollock(m_EPollLock);
|
||||
ScopedLock epollock(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
|
||||
if (p == m_mPolls.end())
|
||||
{
|
||||
LOGC(ealog.Error, log << "EID:" << eid << " INVALID.");
|
||||
throw CUDTException(MJ_NOTSUP, MN_EIDINVAL);
|
||||
}
|
||||
|
||||
|
@ -487,7 +587,9 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
if (!ed.flags(SRT_EPOLL_ENABLE_EMPTY) && ed.watch_empty() && ed.m_sLocals.empty())
|
||||
{
|
||||
// Empty EID is not allowed, report error.
|
||||
throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
//throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
LOGC(ealog.Error, log << "EID:" << eid << " no sockets to check, this would deadlock");
|
||||
throw CUDTException(MJ_NOTSUP, MN_EEMPTY, 0);
|
||||
}
|
||||
|
||||
if (ed.flags(SRT_EPOLL_ENABLE_OUTPUTCHECK))
|
||||
|
@ -507,13 +609,13 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
{
|
||||
++it_next;
|
||||
IF_HEAVY_LOGGING(++total_noticed);
|
||||
if (readfds && ((it->events & UDT_EPOLL_IN) || (it->events & UDT_EPOLL_ERR)))
|
||||
if (readfds && ((it->events & SRT_EPOLL_IN) || (it->events & SRT_EPOLL_ERR)))
|
||||
{
|
||||
if (readfds->insert(it->fd).second)
|
||||
++total;
|
||||
}
|
||||
|
||||
if (writefds && ((it->events & UDT_EPOLL_OUT) || (it->events & UDT_EPOLL_ERR)))
|
||||
if (writefds && ((it->events & SRT_EPOLL_OUT) || (it->events & SRT_EPOLL_ERR)))
|
||||
{
|
||||
if (writefds->insert(it->fd).second)
|
||||
++total;
|
||||
|
@ -530,15 +632,16 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
}
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: REPORTED " << total << "/" << total_noticed
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: REPORTED " << total << "/" << total_noticed
|
||||
<< debug_sockets.str());
|
||||
|
||||
if (lrfds || lwfds)
|
||||
if ((lrfds || lwfds) && !ed.m_sLocals.empty())
|
||||
{
|
||||
#ifdef LINUX
|
||||
const int max_events = ed.m_sLocals.size();
|
||||
epoll_event ev[max_events];
|
||||
int nfds = ::epoll_wait(ed.m_iLocalID, ev, max_events, 0);
|
||||
SRT_ASSERT(max_events > 0);
|
||||
srt::FixedArray<epoll_event> ev(max_events);
|
||||
int nfds = ::epoll_wait(ed.m_iLocalID, ev.data(), ev.size(), 0);
|
||||
|
||||
IF_HEAVY_LOGGING(const int prev_total = total);
|
||||
for (int i = 0; i < nfds; ++ i)
|
||||
|
@ -554,31 +657,32 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
++ total;
|
||||
}
|
||||
}
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: LINUX: picking up " << (total - prev_total) << " ready fds.");
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: LINUX: picking up " << (total - prev_total) << " ready fds.");
|
||||
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
struct timespec tmout = {0, 0};
|
||||
const int max_events = ed.m_sLocals.size();
|
||||
struct kevent ke[max_events];
|
||||
const int max_events = (int)ed.m_sLocals.size();
|
||||
SRT_ASSERT(max_events > 0);
|
||||
srt::FixedArray<struct kevent> ke(max_events);
|
||||
|
||||
int nfds = kevent(ed.m_iLocalID, NULL, 0, ke, max_events, &tmout);
|
||||
int nfds = kevent(ed.m_iLocalID, NULL, 0, ke.data(), (int)ke.size(), &tmout);
|
||||
IF_HEAVY_LOGGING(const int prev_total = total);
|
||||
|
||||
for (int i = 0; i < nfds; ++ i)
|
||||
{
|
||||
if ((NULL != lrfds) && (ke[i].filter == EVFILT_READ))
|
||||
{
|
||||
lrfds->insert(ke[i].ident);
|
||||
lrfds->insert((int)ke[i].ident);
|
||||
++ total;
|
||||
}
|
||||
if ((NULL != lwfds) && (ke[i].filter == EVFILT_WRITE))
|
||||
{
|
||||
lwfds->insert(ke[i].ident);
|
||||
lwfds->insert((int)ke[i].ident);
|
||||
++ total;
|
||||
}
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: Darwin/BSD: picking up " << (total - prev_total) << " ready fds.");
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: Darwin/BSD: picking up " << (total - prev_total) << " ready fds.");
|
||||
|
||||
#else
|
||||
//currently "select" is used for all non-Linux platforms.
|
||||
|
@ -599,7 +703,7 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
if (lwfds)
|
||||
FD_SET(*i, &rqwritefds);
|
||||
if ((int)*i > max_fd)
|
||||
max_fd = *i;
|
||||
max_fd = (int)*i;
|
||||
}
|
||||
|
||||
IF_HEAVY_LOGGING(const int prev_total = total);
|
||||
|
@ -623,34 +727,127 @@ int CEPoll::wait(const int eid, set<SRTSOCKET>* readfds, set<SRTSOCKET>* writefd
|
|||
}
|
||||
}
|
||||
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: select(otherSYS): picking up " << (total - prev_total) << " ready fds.");
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: select(otherSYS): picking up " << (total - prev_total) << " ready fds.");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // END-LOCK: m_EPollLock
|
||||
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: Total of " << total << " READY SOCKETS");
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: Total of " << total << " READY SOCKETS");
|
||||
|
||||
if (total > 0)
|
||||
return total;
|
||||
|
||||
if ((msTimeOut >= 0) && (int64_t(CTimer::getTime() - entertime) >= msTimeOut * int64_t(1000)))
|
||||
if ((msTimeOut >= 0) && (count_microseconds(srt::sync::steady_clock::now() - entertime) >= msTimeOut * int64_t(1000)))
|
||||
{
|
||||
HLOGP(mglog.Debug, "... not waiting longer - timeout");
|
||||
HLOGC(ealog.Debug, log << "EID:" << eid << ": TIMEOUT.");
|
||||
throw CUDTException(MJ_AGAIN, MN_XMTIMEOUT, 0);
|
||||
}
|
||||
|
||||
CTimer::EWait wt ATR_UNUSED = CTimer::waitForEvent();
|
||||
HLOGC(mglog.Debug, log << "CEPoll::wait: EVENT WAITING: "
|
||||
<< (wt == CTimer::WT_TIMEOUT ? "CHECKPOINT" : wt == CTimer::WT_EVENT ? "TRIGGERED" : "ERROR"));
|
||||
const bool wait_signaled SRT_ATR_UNUSED = CGlobEvent::waitForEvent();
|
||||
HLOGC(ealog.Debug, log << "CEPoll::wait: EVENT WAITING: "
|
||||
<< (wait_signaled ? "TRIGGERED" : "CHECKPOINT"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEPoll::release(const int eid)
|
||||
int srt::CEPoll::swait(CEPollDesc& d, map<SRTSOCKET, int>& st, int64_t msTimeOut, bool report_by_exception)
|
||||
{
|
||||
CGuard pg(m_EPollLock);
|
||||
{
|
||||
ScopedLock lg (m_EPollLock);
|
||||
if (!d.flags(SRT_EPOLL_ENABLE_EMPTY) && d.watch_empty() && msTimeOut < 0)
|
||||
{
|
||||
// no socket is being monitored, this may be a deadlock
|
||||
LOGC(ealog.Error, log << "EID:" << d.m_iID << " no sockets to check, this would deadlock");
|
||||
if (report_by_exception)
|
||||
throw CUDTException(MJ_NOTSUP, MN_EEMPTY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
st.clear();
|
||||
|
||||
steady_clock::time_point entertime = steady_clock::now();
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
// Not extracting separately because this function is
|
||||
// for internal use only and we state that the eid could
|
||||
// not be deleted or changed the target CEPollDesc in the
|
||||
// meantime.
|
||||
|
||||
// Here we only prevent the pollset be updated simultaneously
|
||||
// with unstable reading.
|
||||
ScopedLock lg (m_EPollLock);
|
||||
|
||||
if (!d.flags(SRT_EPOLL_ENABLE_EMPTY) && d.watch_empty())
|
||||
{
|
||||
// Empty EID is not allowed, report error.
|
||||
throw CUDTException(MJ_NOTSUP, MN_EEMPTY);
|
||||
}
|
||||
|
||||
if (!d.m_sLocals.empty())
|
||||
{
|
||||
// XXX Add error log
|
||||
// uwait should not be used with EIDs subscribed to system sockets
|
||||
throw CUDTException(MJ_NOTSUP, MN_INVAL);
|
||||
}
|
||||
|
||||
bool empty = d.enotice_empty();
|
||||
|
||||
if (!empty || msTimeOut == 0)
|
||||
{
|
||||
IF_HEAVY_LOGGING(ostringstream singles);
|
||||
// If msTimeOut == 0, it means that we need the information
|
||||
// immediately, we don't want to wait. Therefore in this case
|
||||
// report also when none is ready.
|
||||
int total = 0; // This is a list, so count it during iteration
|
||||
CEPollDesc::enotice_t::iterator i = d.enotice_begin();
|
||||
while (i != d.enotice_end())
|
||||
{
|
||||
++total;
|
||||
st[i->fd] = i->events;
|
||||
IF_HEAVY_LOGGING(singles << "@" << i->fd << ":");
|
||||
IF_HEAVY_LOGGING(PrintEpollEvent(singles, i->events, i->parent->edgeOnly()));
|
||||
const bool edged SRT_ATR_UNUSED = d.checkEdge(i++); // NOTE: potentially deletes `i`
|
||||
IF_HEAVY_LOGGING(singles << (edged ? "<^> " : " "));
|
||||
}
|
||||
|
||||
// Logging into 'singles' because it notifies as to whether
|
||||
// the edge-triggered event has been cleared
|
||||
HLOGC(ealog.Debug, log << "E" << d.m_iID << " rdy=" << total << ": "
|
||||
<< singles.str()
|
||||
<< " TRACKED: " << d.DisplayEpollWatch());
|
||||
return total;
|
||||
}
|
||||
// Don't report any updates because this check happens
|
||||
// extremely often.
|
||||
}
|
||||
|
||||
if ((msTimeOut >= 0) && ((steady_clock::now() - entertime) >= microseconds_from(msTimeOut * int64_t(1000))))
|
||||
{
|
||||
HLOGC(ealog.Debug, log << "EID:" << d.m_iID << ": TIMEOUT.");
|
||||
if (report_by_exception)
|
||||
throw CUDTException(MJ_AGAIN, MN_XMTIMEOUT, 0);
|
||||
return 0; // meaning "none is ready"
|
||||
}
|
||||
|
||||
CGlobEvent::waitForEvent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool srt::CEPoll::empty(const CEPollDesc& d) const
|
||||
{
|
||||
ScopedLock lg (m_EPollLock);
|
||||
return d.watch_empty();
|
||||
}
|
||||
|
||||
int srt::CEPoll::release(const int eid)
|
||||
{
|
||||
ScopedLock pg(m_EPollLock);
|
||||
|
||||
map<int, CEPollDesc>::iterator i = m_mPolls.find(eid);
|
||||
if (i == m_mPolls.end())
|
||||
|
@ -659,7 +856,7 @@ int CEPoll::release(const int eid)
|
|||
#ifdef LINUX
|
||||
// release local/system epoll descriptor
|
||||
::close(i->second.m_iLocalID);
|
||||
#elif defined(BSD) || defined(OSX) || (TARGET_OS_IOS == 1) || (TARGET_OS_TV == 1)
|
||||
#elif defined(BSD) || TARGET_OS_MAC
|
||||
::close(i->second.m_iLocalID);
|
||||
#endif
|
||||
|
||||
|
@ -669,16 +866,29 @@ int CEPoll::release(const int eid)
|
|||
}
|
||||
|
||||
|
||||
int CEPoll::update_events(const SRTSOCKET& uid, std::set<int>& eids, const int events, const bool enable)
|
||||
int srt::CEPoll::update_events(const SRTSOCKET& uid, std::set<int>& eids, const int events, const bool enable)
|
||||
{
|
||||
// As event flags no longer contain only event types, check now.
|
||||
if ((events & ~SRT_EPOLL_EVENTTYPES) != 0)
|
||||
{
|
||||
LOGC(eilog.Fatal, log << "epoll/update: IPE: 'events' parameter shall not contain special flags!");
|
||||
return -1; // still, ignored.
|
||||
}
|
||||
|
||||
int nupdated = 0;
|
||||
vector<int> lost;
|
||||
|
||||
CGuard pg(m_EPollLock);
|
||||
IF_HEAVY_LOGGING(ostringstream debug);
|
||||
IF_HEAVY_LOGGING(debug << "epoll/update: @" << uid << " " << (enable ? "+" : "-"));
|
||||
IF_HEAVY_LOGGING(PrintEpollEvent(debug, events));
|
||||
|
||||
ScopedLock pg (m_EPollLock);
|
||||
for (set<int>::iterator i = eids.begin(); i != eids.end(); ++ i)
|
||||
{
|
||||
map<int, CEPollDesc>::iterator p = m_mPolls.find(*i);
|
||||
if (p == m_mPolls.end())
|
||||
{
|
||||
HLOGC(eilog.Note, log << "epoll/update: E" << *i << " was deleted in the meantime");
|
||||
// EID invalid, though still present in the socket's subscriber list
|
||||
// (dangling in the socket). Postpone to fix the subscruption and continue.
|
||||
lost.push_back(*i);
|
||||
|
@ -692,9 +902,12 @@ int CEPoll::update_events(const SRTSOCKET& uid, std::set<int>& eids, const int e
|
|||
if (!pwait)
|
||||
{
|
||||
// As this is mapped in the socket's data, it should be impossible.
|
||||
LOGC(eilog.Error, log << "epoll/update: IPE: update struck E"
|
||||
<< (*i) << " which is NOT SUBSCRIBED to @" << uid);
|
||||
continue;
|
||||
}
|
||||
|
||||
IF_HEAVY_LOGGING(string tracking = " TRACKING: " + ed.DisplayEpollWatch());
|
||||
// compute new states
|
||||
|
||||
// New state to be set into the permanent state
|
||||
|
@ -704,13 +917,21 @@ int CEPoll::update_events(const SRTSOCKET& uid, std::set<int>& eids, const int e
|
|||
// compute states changes!
|
||||
int changes = pwait->state ^ newstate; // oldState XOR newState
|
||||
if (!changes)
|
||||
{
|
||||
HLOGC(eilog.Debug, log << debug.str() << ": E" << (*i)
|
||||
<< tracking << " NOT updated: no changes");
|
||||
continue; // no changes!
|
||||
}
|
||||
// assign new state
|
||||
pwait->state = newstate;
|
||||
// filter change relating what is watching
|
||||
changes &= pwait->watch;
|
||||
if (!changes)
|
||||
{
|
||||
HLOGC(eilog.Debug, log << debug.str() << ": E" << (*i)
|
||||
<< tracking << " NOT updated: not subscribed");
|
||||
continue; // no change watching
|
||||
}
|
||||
// set events changes!
|
||||
|
||||
// This function will update the notice object associated with
|
||||
|
@ -718,10 +939,75 @@ int CEPoll::update_events(const SRTSOCKET& uid, std::set<int>& eids, const int e
|
|||
// - if enable, it will set event flags, possibly in a new notice object
|
||||
// - if !enable, it will clear event flags, possibly remove notice if resulted in 0
|
||||
ed.updateEventNotice(*pwait, uid, events, enable);
|
||||
++nupdated;
|
||||
|
||||
HLOGC(eilog.Debug, log << debug.str() << ": E" << (*i)
|
||||
<< " TRACKING: " << ed.DisplayEpollWatch());
|
||||
}
|
||||
|
||||
for (vector<int>::iterator i = lost.begin(); i != lost.end(); ++ i)
|
||||
eids.erase(*i);
|
||||
|
||||
return 0;
|
||||
return nupdated;
|
||||
}
|
||||
|
||||
// Debug use only.
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
namespace srt
|
||||
{
|
||||
|
||||
static ostream& PrintEpollEvent(ostream& os, int events, int et_events)
|
||||
{
|
||||
static pair<int, const char*> const namemap [] = {
|
||||
make_pair(SRT_EPOLL_IN, "R"),
|
||||
make_pair(SRT_EPOLL_OUT, "W"),
|
||||
make_pair(SRT_EPOLL_ERR, "E"),
|
||||
make_pair(SRT_EPOLL_UPDATE, "U")
|
||||
};
|
||||
|
||||
int N = Size(namemap);
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
if (events & namemap[i].first)
|
||||
{
|
||||
os << "[";
|
||||
if (et_events & namemap[i].first)
|
||||
os << "^";
|
||||
os << namemap[i].second << "]";
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
string DisplayEpollResults(const std::map<SRTSOCKET, int>& sockset)
|
||||
{
|
||||
typedef map<SRTSOCKET, int> fmap_t;
|
||||
ostringstream os;
|
||||
for (fmap_t::const_iterator i = sockset.begin(); i != sockset.end(); ++i)
|
||||
{
|
||||
os << "@" << i->first << ":";
|
||||
PrintEpollEvent(os, i->second);
|
||||
os << " ";
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
string CEPollDesc::DisplayEpollWatch()
|
||||
{
|
||||
ostringstream os;
|
||||
for (ewatch_t::const_iterator i = m_USockWatchState.begin(); i != m_USockWatchState.end(); ++i)
|
||||
{
|
||||
os << "@" << i->first << ":";
|
||||
PrintEpollEvent(os, i->second.watch, i->second.edge);
|
||||
os << " ";
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
} // namespace srt
|
||||
|
||||
#endif
|
||||
|
|
276
trunk/3rdparty/srt-1-fit/srtcore/epoll.h
vendored
Executable file → Normal file
276
trunk/3rdparty/srt-1-fit/srtcore/epoll.h
vendored
Executable file → Normal file
|
@ -50,8 +50,8 @@ modified by
|
|||
Haivision Systems Inc.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __UDT_EPOLL_H__
|
||||
#define __UDT_EPOLL_H__
|
||||
#ifndef INC_SRT_EPOLL_H
|
||||
#define INC_SRT_EPOLL_H
|
||||
|
||||
|
||||
#include <map>
|
||||
|
@ -59,11 +59,21 @@ modified by
|
|||
#include <list>
|
||||
#include "udt.h"
|
||||
|
||||
|
||||
struct CEPollDesc
|
||||
namespace srt
|
||||
{
|
||||
const int m_iID; // epoll ID
|
||||
|
||||
class CUDT;
|
||||
class CRendezvousQueue;
|
||||
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
|
||||
|
@ -86,40 +96,62 @@ struct CEPollDesc
|
|||
{
|
||||
/// Events the subscriber is interested with. Only those will be
|
||||
/// regarded when updating event flags.
|
||||
int watch;
|
||||
int32_t watch;
|
||||
|
||||
/// Which events should be edge-triggered. When the event isn't
|
||||
/// mentioned in `watch`, this bit flag is disregarded. Otherwise
|
||||
/// it means that the event is to be waited for persistent state
|
||||
/// if this flag is not present here, and for edge trigger, if
|
||||
/// the flag is present here.
|
||||
int edge;
|
||||
int32_t edge;
|
||||
|
||||
/// The current persistent state. This is usually duplicated in
|
||||
/// a dedicated state object in `m_USockEventNotice`, however the state
|
||||
/// here will stay forever as is, regardless of the edge/persistent
|
||||
/// subscription mode for the event.
|
||||
int state;
|
||||
int32_t state;
|
||||
|
||||
/// The iterator to `m_USockEventNotice` container that contains the
|
||||
/// event notice object for this subscription, or the value from
|
||||
/// `nullNotice()` if there is no such object.
|
||||
enotice_t::iterator notit;
|
||||
|
||||
Wait(int sub, bool etr, enotice_t::iterator i)
|
||||
Wait(explicit_t<int32_t> sub, explicit_t<int32_t> etr, enotice_t::iterator i)
|
||||
:watch(sub)
|
||||
,edge(etr ? sub : 0)
|
||||
,edge(etr)
|
||||
,state(0)
|
||||
,notit(i)
|
||||
{
|
||||
}
|
||||
|
||||
int edgeOnly() { return edge & watch; }
|
||||
|
||||
/// Clear all flags for given direction from the notices
|
||||
/// and subscriptions, and checks if this made the event list
|
||||
/// for this watch completely empty.
|
||||
/// @param direction event type that has to be cleared
|
||||
/// @return true, if this cleared the last event (the caller
|
||||
/// want to remove the subscription for this socket)
|
||||
bool clear(int32_t direction)
|
||||
{
|
||||
if (watch & direction)
|
||||
{
|
||||
watch &= ~direction;
|
||||
edge &= ~direction;
|
||||
state &= ~direction;
|
||||
|
||||
return watch == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<SRTSOCKET, Wait> ewatch_t;
|
||||
|
||||
private:
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
std::string DisplayEpollWatch();
|
||||
#endif
|
||||
|
||||
/// Sockets that are subscribed for events in this eid.
|
||||
ewatch_t m_USockWatchState;
|
||||
|
@ -135,7 +167,10 @@ private:
|
|||
|
||||
enotice_t::iterator nullNotice() { return m_USockEventNotice.end(); }
|
||||
|
||||
public:
|
||||
// Only CEPoll class should have access to it.
|
||||
// Guarding private access to the class is not necessary
|
||||
// within the epoll module.
|
||||
friend class CEPoll;
|
||||
|
||||
CEPollDesc(int id, int localID)
|
||||
: m_iID(id)
|
||||
|
@ -147,13 +182,13 @@ public:
|
|||
static const int32_t EF_NOCHECK_EMPTY = 1 << 0;
|
||||
static const int32_t EF_CHECK_REP = 1 << 1;
|
||||
|
||||
int32_t flags() { return m_Flags; }
|
||||
bool flags(int32_t f) { return (m_Flags & f) != 0; }
|
||||
int32_t flags() const { return m_Flags; }
|
||||
bool flags(int32_t f) const { return (m_Flags & f) != 0; }
|
||||
void set_flags(int32_t flg) { m_Flags |= flg; }
|
||||
void clr_flags(int32_t flg) { m_Flags &= ~flg; }
|
||||
|
||||
// Container accessors for ewatch_t.
|
||||
bool watch_empty() { return m_USockWatchState.empty(); }
|
||||
bool watch_empty() const { return m_USockWatchState.empty(); }
|
||||
Wait* watch_find(SRTSOCKET sock)
|
||||
{
|
||||
ewatch_t::iterator i = m_USockWatchState.find(sock);
|
||||
|
@ -165,13 +200,16 @@ public:
|
|||
// Container accessors for enotice_t.
|
||||
enotice_t::iterator enotice_begin() { return m_USockEventNotice.begin(); }
|
||||
enotice_t::iterator enotice_end() { return m_USockEventNotice.end(); }
|
||||
enotice_t::const_iterator enotice_begin() const { return m_USockEventNotice.begin(); }
|
||||
enotice_t::const_iterator enotice_end() const { return m_USockEventNotice.end(); }
|
||||
bool enotice_empty() const { return m_USockEventNotice.empty(); }
|
||||
|
||||
const int m_iLocalID; // local system epoll ID
|
||||
std::set<SYSSOCKET> m_sLocals; // set of local (non-UDT) descriptors
|
||||
|
||||
std::pair<ewatch_t::iterator, bool> addWatch(SRTSOCKET sock, int32_t events, bool edgeTrg)
|
||||
std::pair<ewatch_t::iterator, bool> addWatch(SRTSOCKET sock, explicit_t<int32_t> events, explicit_t<int32_t> et_events)
|
||||
{
|
||||
return m_USockWatchState.insert(std::make_pair(sock, Wait(events, edgeTrg, nullNotice())));
|
||||
return m_USockWatchState.insert(std::make_pair(sock, Wait(events, et_events, nullNotice())));
|
||||
}
|
||||
|
||||
void addEventNotice(Wait& wait, SRTSOCKET sock, int events)
|
||||
|
@ -224,6 +262,12 @@ public:
|
|||
m_USockWatchState.erase(i);
|
||||
}
|
||||
|
||||
void clearAll()
|
||||
{
|
||||
m_USockEventNotice.clear();
|
||||
m_USockWatchState.clear();
|
||||
}
|
||||
|
||||
void removeExistingNotices(Wait& wait)
|
||||
{
|
||||
m_USockEventNotice.erase(wait.notit);
|
||||
|
@ -281,12 +325,44 @@ public:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// This should work in a loop around the notice container of
|
||||
/// the given eid container and clear out the notice for
|
||||
/// particular event type. If this has cleared effectively the
|
||||
/// last existing event, it should return the socket id
|
||||
/// so that the caller knows to remove it also from subscribers.
|
||||
///
|
||||
/// @param i iterator in the notice container
|
||||
/// @param event event type to be cleared
|
||||
/// @retval (socket) Socket to be removed from subscriptions
|
||||
/// @retval SRT_INVALID_SOCK Nothing to be done (associated socket
|
||||
/// still has other subscriptions)
|
||||
SRTSOCKET clearEventSub(enotice_t::iterator i, int event)
|
||||
{
|
||||
// We need to remove the notice and subscription
|
||||
// for this event. The 'i' iterator is safe to
|
||||
// delete, even indirectly.
|
||||
|
||||
// This works merely like checkEdge, just on request to clear the
|
||||
// identified event, if found.
|
||||
if (i->events & event)
|
||||
{
|
||||
// The notice has a readiness flag on this event.
|
||||
// This means that there exists also a subscription.
|
||||
Wait* w = i->parent;
|
||||
if (w->clear(event))
|
||||
return i->fd;
|
||||
}
|
||||
|
||||
return SRT_INVALID_SOCK;
|
||||
}
|
||||
};
|
||||
|
||||
class CEPoll
|
||||
{
|
||||
friend class CUDT;
|
||||
friend class CRendezvousQueue;
|
||||
friend class srt::CUDT;
|
||||
friend class srt::CUDTGroup;
|
||||
friend class srt::CRendezvousQueue;
|
||||
|
||||
public:
|
||||
CEPoll();
|
||||
|
@ -294,90 +370,122 @@ public:
|
|||
|
||||
public: // for CUDTUnited API
|
||||
|
||||
/// create a new EPoll.
|
||||
/// @return new EPoll ID if success, otherwise an error number.
|
||||
/// create a new EPoll.
|
||||
/// @return new EPoll ID if success, otherwise an error number.
|
||||
int create(CEPollDesc** ppd = 0);
|
||||
|
||||
int create();
|
||||
|
||||
/// add a UDT socket to an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT Socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
/// delete all user sockets (SRT sockets) from an EPoll
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @return 0
|
||||
int clear_usocks(int eid);
|
||||
|
||||
int add_usock(const int eid, const SRTSOCKET& u, const int* events = NULL) { return update_usock(eid, u, events); }
|
||||
|
||||
/// add a system socket to an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] s system Socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
/// add a system socket to an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] s system Socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
|
||||
|
||||
/// remove a UDT socket event from an EPoll; socket will be removed if no events to watch.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT socket ID.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int remove_usock(const int eid, const SRTSOCKET& u) { static const int Null(0); return update_usock(eid, u, &Null);}
|
||||
|
||||
/// remove a system socket event from an EPoll; socket will be removed if no events to watch.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] s system socket ID.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
/// remove a system socket event from an EPoll; socket will be removed if no events to watch.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] s system socket ID.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int remove_ssock(const int eid, const SYSSOCKET& s);
|
||||
/// update a UDT socket events from an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
/// update a UDT socket events from an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int update_usock(const int eid, const SRTSOCKET& u, const int* events);
|
||||
|
||||
/// update a system socket events from an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
/// update a system socket events from an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [in] u UDT socket ID.
|
||||
/// @param [in] events events to watch.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int update_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
|
||||
|
||||
/// wait for EPoll events or timeout.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [out] readfds UDT sockets available for reading.
|
||||
/// @param [out] writefds UDT sockets available for writing.
|
||||
/// @param [in] msTimeOut timeout threshold, in milliseconds.
|
||||
/// @param [out] lrfds system file descriptors for reading.
|
||||
/// @param [out] lwfds system file descriptors for writing.
|
||||
/// @return number of sockets available for IO.
|
||||
/// wait for EPoll events or timeout.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [out] readfds UDT sockets available for reading.
|
||||
/// @param [out] writefds UDT sockets available for writing.
|
||||
/// @param [in] msTimeOut timeout threshold, in milliseconds.
|
||||
/// @param [out] lrfds system file descriptors for reading.
|
||||
/// @param [out] lwfds system file descriptors for writing.
|
||||
/// @return number of sockets available for IO.
|
||||
|
||||
int wait(const int eid, std::set<SRTSOCKET>* readfds, std::set<SRTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds, std::set<SYSSOCKET>* lwfds);
|
||||
|
||||
/// wait for EPoll events or timeout optimized with explicit EPOLL_ERR event and the edge mode option.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [out] fdsSet array of user socket events (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR).
|
||||
/// @param [int] fdsSize of fds array
|
||||
/// @param [in] msTimeOut timeout threshold, in milliseconds.
|
||||
/// @return total of available events in the epoll system (can be greater than fdsSize)
|
||||
typedef std::map<SRTSOCKET, int> fmap_t;
|
||||
|
||||
/// Lightweit and more internal-reaching version of `uwait` for internal use only.
|
||||
/// This function wait for sockets to be ready and reports them in `st` map.
|
||||
///
|
||||
/// @param d the internal structure of the epoll container
|
||||
/// @param st output container for the results: { socket_type, event }
|
||||
/// @param msTimeOut timeout after which return with empty output is allowed
|
||||
/// @param report_by_exception if true, errors will result in exception intead of returning -1
|
||||
/// @retval -1 error occurred
|
||||
/// @retval >=0 number of ready sockets (actually size of `st`)
|
||||
int swait(CEPollDesc& d, fmap_t& st, int64_t msTimeOut, bool report_by_exception = true);
|
||||
|
||||
/// Empty subscription check - for internal use only.
|
||||
bool empty(const CEPollDesc& d) const;
|
||||
|
||||
/// Reports which events are ready on the given socket.
|
||||
/// @param mp socket event map retirned by `swait`
|
||||
/// @param sock which socket to ask
|
||||
/// @return event flags for given socket, or 0 if none
|
||||
static int ready(const fmap_t& mp, SRTSOCKET sock)
|
||||
{
|
||||
fmap_t::const_iterator y = mp.find(sock);
|
||||
if (y == mp.end())
|
||||
return 0;
|
||||
return y->second;
|
||||
}
|
||||
|
||||
/// Reports whether socket is ready for given event.
|
||||
/// @param mp socket event map retirned by `swait`
|
||||
/// @param sock which socket to ask
|
||||
/// @param event which events it should be ready for
|
||||
/// @return true if the given socket is ready for given event
|
||||
static bool isready(const fmap_t& mp, SRTSOCKET sock, SRT_EPOLL_OPT event)
|
||||
{
|
||||
return (ready(mp, sock) & event) != 0;
|
||||
}
|
||||
|
||||
// Could be a template directly, but it's now hidden in the imp file.
|
||||
void clear_ready_usocks(CEPollDesc& d, int direction);
|
||||
|
||||
/// wait for EPoll events or timeout optimized with explicit EPOLL_ERR event and the edge mode option.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @param [out] fdsSet array of user socket events (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR).
|
||||
/// @param [int] fdsSize of fds array
|
||||
/// @param [in] msTimeOut timeout threshold, in milliseconds.
|
||||
/// @return total of available events in the epoll system (can be greater than fdsSize)
|
||||
|
||||
int uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
|
||||
|
||||
/// close and release an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
/// close and release an EPoll.
|
||||
/// @param [in] eid EPoll ID.
|
||||
/// @return 0 if success, otherwise an error number.
|
||||
|
||||
int release(const int eid);
|
||||
|
||||
public: // for CUDT to acknowledge IO status
|
||||
|
||||
/// Update events available for a UDT socket.
|
||||
/// @param [in] uid UDT socket ID.
|
||||
/// @param [in] eids EPoll IDs to be set
|
||||
/// @param [in] events Combination of events to update
|
||||
/// @param [in] enable true -> enable, otherwise disable
|
||||
/// @return 0 if success, otherwise an error number
|
||||
/// Update events available for a UDT socket. At the end this function
|
||||
/// counts the number of updated EIDs with given events.
|
||||
/// @param [in] uid UDT socket ID.
|
||||
/// @param [in] eids EPoll IDs to be set
|
||||
/// @param [in] events Combination of events to update
|
||||
/// @param [in] enable true -> enable, otherwise disable
|
||||
/// @return -1 if invalid events, otherwise the number of changes
|
||||
|
||||
int update_events(const SRTSOCKET& uid, std::set<int>& eids, int events, bool enable);
|
||||
|
||||
|
@ -385,11 +493,17 @@ public: // for CUDT to acknowledge IO status
|
|||
|
||||
private:
|
||||
int m_iIDSeed; // seed to generate a new ID
|
||||
pthread_mutex_t m_SeedLock;
|
||||
srt::sync::Mutex m_SeedLock;
|
||||
|
||||
std::map<int, CEPollDesc> m_mPolls; // all epolls
|
||||
pthread_mutex_t m_EPollLock;
|
||||
mutable srt::sync::Mutex m_EPollLock;
|
||||
};
|
||||
|
||||
#if ENABLE_HEAVY_LOGGING
|
||||
std::string DisplayEpollResults(const std::map<SRTSOCKET, int>& sockset);
|
||||
#endif
|
||||
|
||||
} // namespace srt
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue