alternative transport: snapcast protocol over RIST by using libRIST
Implements snapcast protocol over RIST (Reliable Internet Stream Transport)
RIST is an open protocol for low-latency, reliable streaming over unreliable IP networks, ideal for live audio/video contribution and broadcasting. It uses UDP for low-latency transport, with RTP for media synchronization, and adds reliability through ARQ (Automatic Repeat reQuest) and optional FEC (Forward Error Correction).
It is primarily designed for video, but this PR leverages it for audio streaming, benefiting from its robustness and low-latency capabilities. As RIST is bidirectional and multiplexed (with virtual ports), the original snapcast protocol could be used without modification.
This is an alternative transport to the already implemented: TCP and WS. It uses libRIST for the heavy lifting.
Pull Request Checklist
-
[x] Contributions must be licensed under the GPL-3.0 License
-
[x] This project loosely follows the Google C++ Style Guide
-
[x] For better compatibility with embedded toolchains, the used C++ standard should be limited to C++17
-
[x] Code should be formatted by running
make reformat -
[x] Branch from the
developbranch and ensure it is up to date with the currentdevelopbranch before submitting your pull request. If it doesn't merge cleanly withdevelop, you may be asked to resolve the conflicts. Pull requests to master will be closed. -
[x] Commits should be as small as possible while ensuring that each commit is correct independently (i.e., each commit should compile and pass tests).
-
[x] Pull requests must not contain compiled sources (already set by the default .gitignore) or binary files
-
[x] Test your changes as thoroughly as possible before you commit them. Preferably, automate your test by unit/integration tests. If tested manually, provide information about the test scope in the PR description (e.g. “Test passed: Upgrade version from 0.42 to 0.42.23.”).
-
Create Work In Progress [WIP] pull requests only if you need clarification or an explicit review before you can continue your work item.
-
If your patch is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment, or you can ask for a review by contacting us via email.
-
Post review:
- If a review requires you to change your commit(s), please test the changes again.
- Amend the affected commit(s) and force push onto your branch.
- Set respective comments in your GitHub review to resolved.
- Create a general PR comment to notify the reviewers that your amendments are ready for another round of review.
There is extreme madness going on with CI/macos. I probably need a hand for fixing that, as I cannot align
In file included from /Users/runner/work/snapcast/snapcast/client/client_connection.cpp:20:
/Users/runner/work/snapcast/snapcast/client/client_connection.hpp:28:10: fatal error: 'boost/asio/any_io_executor.hpp' file not found
28 | #include <boost/asio/any_io_executor.hpp>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
problems with boost with the changes I made.
There seem to be random issues on macos in several branches, regarding boost and the IOKit.framework. A re-run of the failed jobs seem to succeed in most cases.
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/IOKitLib.h:52:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/OSMessageNotification.h:102:30: error: zero size arrays are an extension [-Werror,-Wzero-length-array]
102 | unsigned char content[0];
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/OSMessageNotification.h:130:30: error: zero size arrays are an extension [-Werror,-Wzero-length-array]
130 | unsigned char content[0];
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/OSMessageNotification.h:148:14: error: zero size arrays are an extension [-Werror,-Wzero-length-array]
148 | void * args[0] __attribute__ ((packed));
[ 31%] Building CXX object server/CMakeFiles/snapserver.dir/control_requests.cpp.o
| ^
cd /Users/runner/work/snapcast/snapcast/build/server && ccache /usr/bin/c++ -DBOOST_ASIO_NO_TS_EXECUTORS -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_PROCESS_VERSION=1 -DFREEBSD -DHAS_BONJOUR -DHAS_DAEMON -DHAS_EXPAT -DHAS_FLAC -DHAS_OGG -DHAS_OPENSSL -DHAS_OPUS -DHAS_SOXR -DHAS_VORBIS -DHAS_VORBIS_ENC -DMACOS -DVERSION=\"0.32.4\" -I/Users/runner/work/snapcast/snapcast -I/Users/runner/work/snapcast/snapcast/include -I/Users/runner/work/snapcast/snapcast/server -I/opt/homebrew/Cellar/libogg/1.3.6/include -I/opt/homebrew/Cellar/libvorbis/1.3.7/include -I/opt/homebrew/Cellar/flac/1.5.0/include -I/opt/homebrew/Cellar/opus/1.5.2/include/opus -I/opt/homebrew/Cellar/libsoxr/0.1.3/include -isystem /Users/runner/work/snapcast/snapcast/server/boost_1_89_0 -isystem /opt/homebrew/Cellar/openssl@3/3.5.2/include -I/usr/local/include -DCMAKE_CXX_FLAGS=-DJSON_HAS_CPP_14 -g -std=gnu++17 -arch arm64 -Wall -Wextra -pedantic -Wno-unused-function -Wno-deprecated-declarations -Werror -MD -MT server/CMakeFiles/snapserver.dir/control_requests.cpp.o -MF CMakeFiles/snapserver.dir/control_requests.cpp.o.d -o CMakeFiles/snapserver.dir/control_requests.cpp.o -c /Users/runner/work/snapcast/snapcast/server/control_requests.cpp
In file included from /Users/runner/work/snapcast/snapcast/client/client_connection.cpp:20:
/Users/runner/work/snapcast/snapcast/client/client_connection.hpp:28:10: fatal error: 'boost/asio/any_io_executor.hpp' file not found
28 | #include <boost/asio/any_io_executor.hpp>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 errors generated.
Thanks, but I'm not sure yet if I will pull this in, as I'm already considering to deprecate plain TCP in favor of WS only (which supports also TLS (WSS)) and would make the code base smaller and easier to maintain. In the next release plain TCP can be deactivated in the config already, so it's no more "always on", lowering also the attack surface by having one less server port.
Well, I'm fine with making TCP optional - but I also have to admit that I normally use TCP (and only try WS for android and browser use). I'm not completely in that, but I think that WS should have considerably more overhead than TCP.
The RIST stuff has the potential to diminish the overhead even further - it is basically UDP (and it would support broadcasting and multicasting - however I so far haven't tried that).
All in all, this is all about the use cases which drive people to use snapcast at all. I think there are people out there that use snapcast mainly with OPCs (server and client). TCP might be important for that use case.
I set up the poll #1441 to get more information about the usage pattern of snapcast regarding transports.
My motivation to implement this is to avoid the TCP overhead without sacrificing reliability. IMHO, RIST is well suited for the task, even better than TCP.
RIST includes very interesting features like broadcasting, multicasting and encryption. (However, all this is not addressed in this PR, which only provides a basic RIST implementation.)