Skip to content

Commit c9d2085

Browse files
authored
Merge pull request #14 from Haivision/development
2 parents 55b20f9 + 17be276 commit c9d2085

23 files changed

Lines changed: 541 additions & 96 deletions

.github/workflows/abi.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
run: |
2727
cd gitview_pr
2828
mkdir _build && cd _build
29-
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_UNITTESTS=OFF ../
29+
cmake -DCMAKE_BUILD_TYPE=Debug ../
3030
- id: build
3131
name: Build and dump
3232
run: |
@@ -81,7 +81,7 @@ jobs:
8181
fi
8282
cd gitview_base
8383
mkdir _build && cd _build
84-
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_UNITTESTS=OFF ../
84+
cmake -DCMAKE_BUILD_TYPE=Debug ../
8585
- id: build_tag
8686
name: Build and dump
8787
if: ${{ success() }}

.github/workflows/cxx11-ubuntu.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ on:
99
jobs:
1010
build:
1111
name: ubuntu
12-
runs-on: ubuntu-22.04
12+
runs-on: ubuntu-latest
1313
steps:
1414
- uses: actions/checkout@v3
1515
- name: configure
1616
run: |
1717
mkdir _build && cd _build
1818
cmake ../ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=ON -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_TESTING=ON -DENABLE_EXAMPLES=ON -DENABLE_CODE_COVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
1919
- name: build
20-
# That below is likely SonarQube remains, which was removed earlier.
21-
#run: cd _build && build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build .
2220
run: cd _build && cmake --build .
2321
- name: test
2422
run: |

CMakeLists.txt

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ if ("${USE_CXX_STD_LIB}" EQUAL 98)
469469
# but on Windows we don't support non-C++11 compiling anymore.
470470
add_definitions(-DHVU_EXT_INCLUDE_SYNC="../srtcore/srt_sync_cxx98.h")
471471
else()
472-
string(APPEND FEATURE_REPORT "LOGGER_SYNC=std ")
472+
string(APPEND FEATURE_REPORT "LOGGER_SYNC=c++std ")
473473
endif()
474474

475475
# add extra warning flags for gccish compilers
@@ -494,6 +494,7 @@ message(STATUS "WARNING OPTIONS: ${SRT_GCC_WARN}")
494494
# --------------------------------------------
495495
# Post-option variable synchronization
496496
# and option-to-preprocessor-macro transition
497+
# (Optional features)
497498
# --------------------------------------------
498499

499500
# Global independet settings
@@ -525,34 +526,6 @@ if (NOT DEFINED SRT_LOG_SLOWDOWN_FREQ_MS)
525526
endif()
526527
list(APPEND SRT_EXTRA_CFLAGS "-DSRT_LOG_SLOWDOWN_FREQ_MS=${SRT_LOG_SLOWDOWN_FREQ_MS}")
527528

528-
if (NOT ENABLE_STDCXX_SYNC)
529-
if (ENABLE_MONOTONIC_CLOCK)
530-
# Require monotonic clock, unless it's explicitly set OFF
531-
list(PREPEND CMAKE_REQUIRED_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
532-
533-
# Note: pthread_condattr_setclock doesn't exist on some systems, at least
534-
# old versions of Android (__ANDROID_API__ < 21) are known to not provide it
535-
check_symbol_exists(pthread_condattr_setclock "pthread.h" HAVE_PTHREAD_CONDATTR_SETCLOCK)
536-
test_requires_clock_gettime(HAVE_MONOTONIC_CLOCK_GETTIME MONOTONIC_CLOCK_LINKLIB)
537-
if (NOT HAVE_MONOTONIC_CLOCK_GETTIME OR NOT HAVE_PTHREAD_CONDATTR_SETCLOCK)
538-
message(FATAL_ERROR "Your platform does not support CLOCK_MONOTONIC. Build with -DENABLE_MONOTONIC_CLOCK=OFF.")
539-
endif()
540-
if (NOT MONOTONIC_CLOCK_LINKLIB STREQUAL "")
541-
set (WITH_EXTRALIBS "${WITH_EXTRALIBS} ${MONOTONIC_CLOCK_LINKLIB}")
542-
endif()
543-
add_definitions(-DSRT_ENABLE_MONOTONIC_CLOCK=1)
544-
string(APPEND FEATURE_REPORT "SYNC=POSIX CLOCK=MONOTONIC ")
545-
message(STATUS "SYNC LIBRARY: POSIX, MONOTONIC CLOCK: ON")
546-
else()
547-
string(APPEND FEATURE_REPORT "SYNC=POSIX CLOCK=SYSTEM ")
548-
message(WARNING
549-
"ENABLE_MONOTONIC_CLOCK is OFF. This is dangerous.
550-
SRT may malfunction, if the system time is changed during transmission.")
551-
endif()
552-
else()
553-
string(APPEND FEATURE_REPORT "SYNC=C++std ")
554-
endif()
555-
556529
if (USE_GNUSTL)
557530
pkg_check_modules (GNUSTL REQUIRED gnustl)
558531
link_directories(${GNUSTL_LIBRARY_DIRS})
@@ -673,6 +646,7 @@ endif()
673646
if (LINUX)
674647
# This is an option supported only on Linux
675648
add_definitions(-DSRT_ENABLE_BINDTODEVICE)
649+
string(APPEND FEATURE_REPORT "BINDTODEVICE=ON ")
676650
endif()
677651

678652
if (USE_STATIC_LIBSTDCXX)
@@ -698,20 +672,71 @@ else ()
698672
message(STATUS "Threads: cmake-default: ${PTHREAD_LIBRARY}")
699673
endif()
700674

701-
# To avoid the need for other judgments when ENABLE_STDCXX_SYNC is OFF in the future, this is a separate conditional statement.
702-
if (NOT ENABLE_STDCXX_SYNC AND ENABLE_MONOTONIC_CLOCK)
675+
# Check the feature of PTHREAD providing pthread_atfork function.
676+
# Regardless of the current thread support library, this is a function
677+
# called as a callback at fork() call. This is required so that SRT
678+
# library can be used with applications that do fork().
679+
680+
if (NOT MICROSOFT AND NOT MINGW)
681+
# Do not enforce pthread library in case of MICROSOFT
682+
# because it dosn't need fork() support (even if someone
683+
# might want to try to compile for Windows with pthreads).
684+
703685
list(PREPEND CMAKE_REQUIRED_LIBRARIES "${PTHREAD_LIBRARY}")
704686
unset(CMAKE_REQUIRED_QUIET)
705-
check_symbol_exists(pthread_condattr_setclock "pthread.h" HAVE_PTHREAD_CONDATTR_SETCLOCK)
706-
message(STATUS "Checking pthread_condattr_setclock: '${HAVE_PTHREAD_CONDATTR_SETCLOCK}'")
707-
if ("${HAVE_PTHREAD_CONDATTR_SETCLOCK}" STREQUAL "1")
708-
string(APPEND FEATURE_REPORT "PTHREAD_COND_CLOCK=monotonic ")
709-
add_definitions(-DHAVE_PTHREAD_CONDATTR_SETCLOCK=1)
710-
else ()
711-
string(APPEND FEATURE_REPORT "PTHREAD_COND_CLOCK=system ")
712-
message(WARNING "NOT FOUND pthread_cond_timedwait. pthread_cond_timedwait will use system clock. Recommended -DENABLE_STDCXX_SYNC=ON")
687+
688+
check_symbol_exists(pthread_atfork "pthread.h" HAVE_PTHREAD_ATFORK)
689+
if ("${HAVE_PTHREAD_ATFORK}" STREQUAL "1")
690+
add_definitions(-DHAVE_PTHREAD_ATFORK=1)
691+
string(APPEND FEATURE_REPORT "ATFORK=ON ")
713692
endif ()
714-
endif ()
693+
endif()
694+
695+
if (NOT ENABLE_STDCXX_SYNC)
696+
if (ENABLE_MONOTONIC_CLOCK)
697+
# Require monotonic clock, unless it's explicitly set OFF
698+
list(PREPEND CMAKE_REQUIRED_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
699+
700+
# Note: pthread_condattr_setclock doesn't exist on some systems, at least
701+
# old versions of Android (__ANDROID_API__ < 21) are known to not provide it
702+
check_symbol_exists(pthread_condattr_setclock "pthread.h" HAVE_PTHREAD_CONDATTR_SETCLOCK)
703+
test_requires_clock_gettime(HAVE_MONOTONIC_CLOCK_GETTIME MONOTONIC_CLOCK_LINKLIB)
704+
if (NOT HAVE_MONOTONIC_CLOCK_GETTIME OR NOT HAVE_PTHREAD_CONDATTR_SETCLOCK)
705+
message(FATAL_ERROR "Your platform does not support CLOCK_MONOTONIC. Build with -DENABLE_MONOTONIC_CLOCK=OFF.")
706+
endif()
707+
if (NOT MONOTONIC_CLOCK_LINKLIB STREQUAL "")
708+
set (WITH_EXTRALIBS "${WITH_EXTRALIBS} ${MONOTONIC_CLOCK_LINKLIB}")
709+
endif()
710+
add_definitions(-DSRT_ENABLE_MONOTONIC_CLOCK=1)
711+
string(APPEND FEATURE_REPORT "SYNC=POSIX CLOCK=monotonic ")
712+
message(STATUS "SYNC LIBRARY: POSIX, MONOTONIC CLOCK: ON")
713+
714+
# Add-unique not supported in cmake, use unload version
715+
list(FIND CMAKE_REQUIRED_QUIET "${PTHREAD_LIBRARY}" HAVE_ALREADY)
716+
if (NOT HAVE_ALREADY)
717+
list(PREPEND CMAKE_REQUIRED_LIBRARIES "${PTHREAD_LIBRARY}")
718+
endif()
719+
unset(CMAKE_REQUIRED_QUIET)
720+
check_symbol_exists(pthread_condattr_setclock "pthread.h" HAVE_PTHREAD_CONDATTR_SETCLOCK)
721+
message(STATUS "Checking pthread_condattr_setclock: '${HAVE_PTHREAD_CONDATTR_SETCLOCK}'")
722+
if ("${HAVE_PTHREAD_CONDATTR_SETCLOCK}" STREQUAL "1")
723+
string(APPEND FEATURE_REPORT "PTHREAD_COND_CLOCK=monotonic ")
724+
add_definitions(-DHAVE_PTHREAD_CONDATTR_SETCLOCK=1)
725+
else ()
726+
string(APPEND FEATURE_REPORT "PTHREAD_COND_CLOCK=system ")
727+
message(WARNING "NOT FOUND pthread_cond_timedwait. pthread_cond_timedwait will use system clock. Recommended -DENABLE_STDCXX_SYNC=ON")
728+
endif ()
729+
730+
else()
731+
string(APPEND FEATURE_REPORT "SYNC=POSIX CLOCK=SYSTEM PTHREAD_COND_CLOCK=system ")
732+
message(WARNING
733+
"ENABLE_MONOTONIC_CLOCK is OFF. This is dangerous.
734+
SRT may malfunction, if the system time is changed during transmission.")
735+
endif()
736+
else()
737+
string(APPEND FEATURE_REPORT "SYNC=C++std ")
738+
endif()
739+
715740

716741
# When you use crosscompiling, you have to take care that PKG_CONFIG_PATH
717742
# and CMAKE_PREFIX_PATH are set properly.

docs/API/API-functions.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,13 +2968,13 @@ associated with the last error. The system error is:
29682968
const char* srt_strerror(int code, int errnoval);
29692969
```
29702970

2971-
Returns a string message that represents a given SRT error code and possibly the
2972-
`errno` value, if not 0.
2971+
Returns a string message that represents a given SRT error code.
29732972

2974-
**NOTE:** *This function isn't thread safe. It uses a static variable to hold the
2975-
error description. There's no problem with using it in a multithreaded environment,
2976-
as long as only one thread in the whole application calls this function at the
2977-
moment*
2973+
**NOTE:** *The `errnoval` parameter is ignored. This function's old version
2974+
was intended to get both the SRT error description and system error description,
2975+
but this requires resolution of the reentrancy problem and dynamic strings.
2976+
For getting the error description for a system error, you need to use the
2977+
`strerror` function or some of its reentrant version.*
29782978

29792979

29802980
[:arrow_up: &nbsp; Back to List of Functions & Structures](#srt-api-functions)

examples/fork-test/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
TARGETS=srt_server srt_client
2+
3+
all: $(TARGETS)
4+
5+
%: %.c
6+
$(CC) $< `pkg-config --cflags --libs srt` -o `basename $< .c`
7+
8+
clean:
9+
rm -f $(TARGETS)

examples/fork-test/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
The `srt_server` and `srt_client` apps should be compiled using
2+
external installation of SRT (e.g. in the local directory), each
3+
one as a single program. This is not compiled as a part of SRT.
4+
5+
If you want to use a local installation, simply set `PKG_CONFIG_PATH`
6+
environment variable to point to the local installation directory with
7+
"lib/pkgconfig" or "lib64/pkgconfig" suffix.

examples/fork-test/srt_client.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <srt/srt.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <arpa/inet.h>
6+
#include <unistd.h>
7+
#include <sys/types.h>
8+
#include <sys/wait.h>
9+
#define SERVER_IP "127.0.0.1"
10+
#define SERVER_PORT 9000
11+
int main() {
12+
if (srt_startup() != 0) {
13+
fprintf(stderr, "Error initializing SRT.\n");
14+
return 1;
15+
}
16+
SRTSOCKET client_sock = srt_create_socket();
17+
if (client_sock == SRT_INVALID_SOCK) {
18+
fprintf(stderr, "Error creating a socket: %s\n", srt_getlasterror_str());
19+
return 1;
20+
}
21+
struct sockaddr_in sa;
22+
memset(&sa, 0, sizeof sa);
23+
sa.sin_family = AF_INET;
24+
sa.sin_port = htons(SERVER_PORT);
25+
inet_pton(AF_INET, SERVER_IP, &sa.sin_addr);
26+
if (srt_connect(client_sock, (struct sockaddr*)&sa, sizeof(sa)) == SRT_ERROR) {
27+
fprintf(stderr, "Error: srt_connect: %s\n", srt_getlasterror_str());
28+
return 1;
29+
}
30+
printf("Connected to SRT server %s:%d\n", SERVER_IP, SERVER_PORT);
31+
const char* message = "Hello from SRT client!";
32+
int bytes = srt_send(client_sock, message, strlen(message));
33+
if (bytes == SRT_ERROR) {
34+
fprintf(stderr, "Sending error: %s\n", srt_getlasterror_str());
35+
} else {
36+
printf("Message sent: %s\n", message);
37+
}
38+
39+
while (1)
40+
{
41+
char buffer[1500];
42+
int nb = srt_recv(client_sock, buffer, sizeof(buffer));
43+
if (nb <= 0)
44+
{
45+
printf("Closed from the server !\n");
46+
srt_close(client_sock);
47+
break;
48+
}
49+
buffer[nb] = 0;
50+
printf("Server has sent: %s\n", buffer);
51+
}
52+
srt_cleanup();
53+
return 0;
54+
}
55+

examples/fork-test/srt_server.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include <srt/srt.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <unistd.h>
6+
#include <sys/types.h>
7+
#include <sys/wait.h>
8+
#include <pthread.h>
9+
#define PORT 9000
10+
11+
int run(char *command) {
12+
pid_t pid = fork();
13+
if (pid < 0) {
14+
perror("fork (intermediate)");
15+
exit(EXIT_FAILURE);
16+
}
17+
if (pid > 0) {
18+
// Parent process
19+
printf("[GRANDPARENT %d] waiting for grand-child process pid=%d to finish...\n",
20+
getpid(), pid);
21+
waitpid(pid, NULL, 0); // Wait for intermediate child
22+
printf("[GRANDPARENT] returning\n");
23+
return 0;
24+
}
25+
// Intermediate process
26+
//srt_cleanup();
27+
if (setsid() < 0) {
28+
perror("setsid");
29+
exit(EXIT_FAILURE);
30+
}
31+
pid_t grandchild_pid = fork();
32+
if (grandchild_pid < 0) {
33+
perror("fork (grandchild)");
34+
exit(EXIT_FAILURE);
35+
}
36+
if (grandchild_pid > 0) {
37+
printf("[PARENT %d] waiting for 10s with child process pid=%d ...\n",
38+
getpid(), grandchild_pid);
39+
// Intermediate process exits immediately
40+
sleep(10);
41+
printf("[PARENT] exitting\n");
42+
exit(0);
43+
}
44+
// Grandchild process
45+
// Redirect stdin to /dev/null
46+
printf("[CHILD %d] Preparing descriptors...\n", getpid());
47+
int devnull = open("/dev/null", O_RDONLY);
48+
if (devnull >= 0) {
49+
dup2(devnull, STDIN_FILENO);
50+
close(devnull);
51+
} else {
52+
perror("open /dev/null");
53+
}
54+
// Redirect stdout to stderr
55+
dup2(STDERR_FILENO, STDOUT_FILENO);
56+
// Execute the command
57+
printf("[CHILD] Executing process '%s'...\n", command);
58+
execl("/bin/sh", "sh", "-c", command, (char *)NULL);
59+
// If execl fails
60+
perror("execl");
61+
exit(EXIT_FAILURE);
62+
}
63+
64+
int main() {
65+
if (srt_startup() != 0) {
66+
fprintf(stderr, "Error initializing SRT.\n");
67+
return 1;
68+
}
69+
70+
SRTSOCKET serv_sock = srt_create_socket();
71+
if (serv_sock == SRT_INVALID_SOCK) {
72+
fprintf(stderr, "Error creating SRT socket: %s\n", srt_getlasterror_str());
73+
return 1;
74+
}
75+
struct sockaddr_in sa;
76+
memset(&sa, 0, sizeof sa);
77+
sa.sin_family = AF_INET;
78+
sa.sin_port = htons(PORT);
79+
sa.sin_addr.s_addr = INADDR_ANY;
80+
if (srt_bind(serv_sock, (struct sockaddr*)&sa, sizeof sa) == SRT_ERROR) {
81+
fprintf(stderr, "Error: srt_bind: %s\n", srt_getlasterror_str());
82+
return 1;
83+
}
84+
if (srt_listen(serv_sock, 5) == SRT_ERROR) {
85+
fprintf(stderr, "Error: srt_listen: %s\n", srt_getlasterror_str());
86+
return 1;
87+
}
88+
printf("SRT server is listening on port %d...\n", PORT);
89+
struct sockaddr_in client_addr;
90+
int addr_len = sizeof(client_addr);
91+
SRTSOCKET client_sock = srt_accept(serv_sock, (struct sockaddr*)&client_addr, &addr_len);
92+
if (client_sock == SRT_INVALID_SOCK) {
93+
fprintf(stderr, "Error: srt_accept: %s\n", srt_getlasterror_str());
94+
return 1;
95+
}
96+
printf("Client connected via SRT !\n");
97+
char buffer[1500];
98+
int bytes = srt_recv(client_sock, buffer, sizeof(buffer));
99+
if (bytes > 0) {
100+
buffer[bytes] = '\0';
101+
printf("Message received: %s\n", buffer);
102+
const char resp [] = "We read you!";
103+
srt_send(client_sock, resp, (sizeof resp)-1);
104+
} else {
105+
printf("Error: reading from srt_recv: %s.\n", srt_getlasterror_str());
106+
}
107+
run("date > /tmp/res");
108+
printf("Server: sleep(1)\n");
109+
sleep(1);
110+
// Nettoyage
111+
printf("Server: closing SRT sockets\n");
112+
srt_close(client_sock);
113+
srt_close(serv_sock);
114+
printf("Server: cleanup\n");
115+
srt_cleanup();
116+
printf("Server: exit\n");
117+
return 0;
118+
}

0 commit comments

Comments
 (0)