diff -Nru ableton-link-3.0.6+dfsg/.appveyor.yml ableton-link-3.1.1+dfsg/.appveyor.yml --- ableton-link-3.0.6+dfsg/.appveyor.yml 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/.appveyor.yml 2024-02-01 14:19:51.000000000 +0000 @@ -78,7 +78,7 @@ GENERATOR: Visual Studio 17 2022 - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 ESP_IDF: true - IDF_RELEASE: v4.3.1 + IDF_RELEASE: v5.1.1 - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 FORMATTING: true @@ -105,7 +105,6 @@ - GENERATOR: Ninja install: - git submodule update --init --recursive - - sudo apt-get update - sudo apt-get install -y libjack-dev portaudio19-dev valgrind build_script: - python3 ci/configure.py --audio-driver $AUDIO_DRIVER --generator "$GENERATOR" --configuration $CONFIGURATION @@ -120,6 +119,7 @@ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 build_script: + - py -3 -m pip install setuptools - py -3 ci/configure.py --audio-driver %AUDIO_DRIVER% --thread-description %THREAD_DESCRIPTION% --generator "%GENERATOR%" --flags="-DCMAKE_SYSTEM_VERSION=10.0.18362.0" - py -3 ci/build.py --configuration %CONFIGURATION% test_script: diff -Nru ableton-link-3.0.6+dfsg/AbletonLinkConfig.cmake ableton-link-3.1.1+dfsg/AbletonLinkConfig.cmake --- ableton-link-3.0.6+dfsg/AbletonLinkConfig.cmake 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/AbletonLinkConfig.cmake 2024-02-01 14:19:51.000000000 +0000 @@ -38,14 +38,9 @@ ) set_property(TARGET Ableton::Link APPEND PROPERTY INTERFACE_LINK_LIBRARIES + atomic pthread ) - if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) - set_property(TARGET Ableton::Link APPEND PROPERTY - INTERFACE_LINK_LIBRARIES - atomic - ) - endif() endif() include(${CMAKE_CURRENT_LIST_DIR}/cmake_include/AsioStandaloneConfig.cmake) diff -Nru ableton-link-3.0.6+dfsg/CMakeLists.txt ableton-link-3.1.1+dfsg/CMakeLists.txt --- ableton-link-3.0.6+dfsg/CMakeLists.txt 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/CMakeLists.txt 2024-02-01 14:19:51.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) project(Link) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) @@ -22,6 +22,8 @@ option(LINK_BUILD_VLD "Build with VLD support (VLD must be installed separately)" OFF) endif() +option(LINK_BUILD_TESTS "Build unit test binaries" ON) + # ____ _ _ # | _ \ __ _| |_| |__ ___ # | |_) / _` | __| '_ \/ __| @@ -36,7 +38,9 @@ include(extensions/abl_link/abl_link.cmake) add_subdirectory(include) +if(LINK_BUILD_TESTS) add_subdirectory(src) +endif() add_subdirectory(examples) add_subdirectory(extensions/abl_link) diff -Nru ableton-link-3.0.6+dfsg/README.md ableton-link-3.1.1+dfsg/README.md --- ableton-link-3.0.6+dfsg/README.md 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/README.md 2024-02-01 14:19:51.000000000 +0000 @@ -108,7 +108,7 @@ [platforms/darwin/Clock.hpp](include/ableton/platforms/darwin/Clock.hpp) - Windows clock implementation in [platforms/windows/Clock.hpp](include/ableton/platforms/windows/Clock.hpp) -- C++ standard library `std::chrono::high_resolution_clock`-based implementation in +- C++ standard library `std::chrono::steady_clock`-based implementation in [platforms/stl/Clock.hpp](include/ableton/platforms/stl/Clock.hpp) Using the system time correctly in the context of an audio callback gets a little diff -Nru ableton-link-3.0.6+dfsg/cmake_include/ConfigureCompileFlags.cmake ableton-link-3.1.1+dfsg/cmake_include/ConfigureCompileFlags.cmake --- ableton-link-3.0.6+dfsg/cmake_include/ConfigureCompileFlags.cmake 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/cmake_include/ConfigureCompileFlags.cmake 2024-02-01 14:19:51.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) set(build_flags_COMMON_LIST) set(build_flags_DEBUG_LIST) diff -Nru ableton-link-3.0.6+dfsg/debian/changelog ableton-link-3.1.1+dfsg/debian/changelog --- ableton-link-3.0.6+dfsg/debian/changelog 2023-02-08 21:31:43.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/changelog 2024-03-02 18:24:58.000000000 +0000 @@ -1,10 +1,34 @@ -ableton-link (3.0.6+dfsg-4~18.04.sav0) bionic; urgency=medium +ableton-link (3.1.1+dfsg-1~18.04.sav0) bionic; urgency=medium * Backport to Bionic * Revert "Use execute_after_dh_* instead of override_dh_*" (compat < 13) * debian/control: Set debhelper-compat (= 11) BD - -- Rob Savoury Wed, 08 Feb 2023 13:31:43 -0800 + -- Rob Savoury Sat, 02 Mar 2024 10:24:58 -0800 + +ableton-link (3.1.1+dfsg-1) unstable; urgency=medium + + * New upstream version 3.1.1+dfsg + + -- IOhannes m zmölnig (Debian/GNU) Mon, 05 Feb 2024 13:57:07 +0100 + +ableton-link (3.1.0+dfsg-2) unstable; urgency=medium + + * Fix FTBFS with catch3 (Closes: #1054677) + + -- IOhannes m zmölnig (Debian/GNU) Mon, 30 Oct 2023 15:40:19 +0100 + +ableton-link (3.1.0+dfsg-1) unstable; urgency=medium + + * New upstream version 3.1.0+dfsg + + Drop patches applied upstream + + Refresh patches + * Switch tests to catch2 + * Update copyright information + + Bump copyright dates + + Re-generate d/copyright_hints + + -- IOhannes m zmölnig (Debian/GNU) Tue, 26 Sep 2023 14:05:30 +0200 ableton-link (3.0.6+dfsg-4) unstable; urgency=medium diff -Nru ableton-link-3.0.6+dfsg/debian/control ableton-link-3.1.1+dfsg/debian/control --- ableton-link-3.0.6+dfsg/debian/control 2023-02-08 21:31:43.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/control 2024-03-02 18:24:58.000000000 +0000 @@ -5,7 +5,7 @@ Uploaders: IOhannes m zmölnig (Debian/GNU) , Build-Depends: - catch , + catch2 (>= 3~) , cmake, debhelper-compat (= 11), libasio-dev, diff -Nru ableton-link-3.0.6+dfsg/debian/copyright ableton-link-3.1.1+dfsg/debian/copyright --- ableton-link-3.0.6+dfsg/debian/copyright 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/copyright 2024-02-05 12:57:07.000000000 +0000 @@ -7,11 +7,11 @@ third_party/* Files: * -Copyright: 2016-2022, Ableton AG, Berlin +Copyright: 2016-2023, Ableton AG, Berlin License: GPL-2+ Files: debian/* -Copyright: 2016-2022, IOhannes m zmölnig (Debian/GNU) +Copyright: 2016-2023, IOhannes m zmölnig (Debian/GNU) License: GPL-2+ License: GPL-2+ diff -Nru ableton-link-3.0.6+dfsg/debian/copyright_hints ableton-link-3.1.1+dfsg/debian/copyright_hints --- ableton-link-3.0.6+dfsg/debian/copyright_hints 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/copyright_hints 2024-02-05 12:57:07.000000000 +0000 @@ -25,8 +25,9 @@ extensions/abl_link/src/abl_link.cpp include/ableton/Link.hpp include/ableton/Link.ipp + include/ableton/discovery/AsioTypes.hpp include/ableton/discovery/InterfaceScanner.hpp - include/ableton/discovery/IpV4Interface.hpp + include/ableton/discovery/IpInterface.hpp include/ableton/discovery/MessageTypes.hpp include/ableton/discovery/NetworkByteStreamSerializable.hpp include/ableton/discovery/Payload.hpp @@ -47,6 +48,7 @@ include/ableton/link/LinearRegression.hpp include/ableton/link/Measurement.hpp include/ableton/link/MeasurementEndpointV4.hpp + include/ableton/link/MeasurementEndpointV6.hpp include/ableton/link/MeasurementService.hpp include/ableton/link/Median.hpp include/ableton/link/NodeId.hpp @@ -71,7 +73,6 @@ include/ableton/platforms/asio/Context.hpp include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp include/ableton/platforms/asio/Socket.hpp - include/ableton/platforms/asio/Util.hpp include/ableton/platforms/darwin/Clock.hpp include/ableton/platforms/darwin/Darwin.hpp include/ableton/platforms/darwin/ThreadFactory.hpp @@ -111,6 +112,7 @@ src/ableton/link/tst_LinearRegression.cpp src/ableton/link/tst_Measurement.cpp src/ableton/link/tst_Median.cpp + src/ableton/link/tst_PeerState.cpp src/ableton/link/tst_Peers.cpp src/ableton/link/tst_Phase.cpp src/ableton/link/tst_PingResponder.cpp @@ -120,12 +122,14 @@ src/ableton/link/tst_TripleBuffer.cpp src/ableton/test/catch/CatchMain.cpp src/ableton/test/serial_io/SchedulerTree.cpp + src/ableton/tst_Link.cpp Copyright: 2016, Ableton AG, Berlin. 2017, Ableton AG, Berlin. 2019, Ableton AG, Berlin. 2020, Ableton AG, Berlin. 2021, Ableton AG, Berlin. 2022, Ableton AG, Berlin. + 2023, Ableton AG, Berlin. License: GPL-2+ FIXME @@ -146,7 +150,9 @@ examples/CMakeLists.txt examples/esp32/CMakeLists.txt examples/esp32/README.md + examples/esp32/dependencies.lock examples/esp32/main/CMakeLists.txt + examples/esp32/main/idf_component.yml examples/esp32/main/main.cpp examples/esp32/sdkconfig.defaults extensions/abl_link/.clang-format diff -Nru ableton-link-3.0.6+dfsg/debian/patches/DEBIAN_catch3.patch ableton-link-3.1.1+dfsg/debian/patches/DEBIAN_catch3.patch --- ableton-link-3.0.6+dfsg/debian/patches/DEBIAN_catch3.patch 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/DEBIAN_catch3.patch 2024-02-05 12:57:07.000000000 +0000 @@ -0,0 +1,39 @@ +Description: Build against catch3 +Author: IOhannes m zmölnig +Origin: Debian +Forwarded: not-needed +Last-Update: 2023-10-30 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- ableton-link.orig/include/ableton/test/CatchWrapper.hpp ++++ ableton-link/include/ableton/test/CatchWrapper.hpp +@@ -35,7 +35,7 @@ + #pragma warning(disable : 5220) + #endif + +-#include ++#include + + #if defined(_MSC_VER) + #pragma warning(pop) +--- ableton-link.orig/CMakeLists.txt ++++ ableton-link/CMakeLists.txt +@@ -39,6 +39,7 @@ + + add_subdirectory(include) + if(LINK_BUILD_TESTS) ++find_package(Catch2 REQUIRED) + add_subdirectory(src) + endif() + add_subdirectory(examples) +--- ableton-link.orig/src/CMakeLists.txt ++++ ableton-link/src/CMakeLists.txt +@@ -77,7 +77,7 @@ + # |___/ + + function(configure_link_test_executable target) +- target_link_libraries(${target} Catch::Catch Ableton::Link) ++ target_link_libraries(${target} Catch2::Catch2WithMain Ableton::Link) + target_compile_definitions(${target} PRIVATE -DCATCH_CONFIG_ENABLE_BENCHMARKING=1) + endfunction() + diff -Nru ableton-link-3.0.6+dfsg/debian/patches/examples.patch ableton-link-3.1.1+dfsg/debian/patches/examples.patch --- ableton-link-3.0.6+dfsg/debian/patches/examples.patch 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/examples.patch 2024-02-05 12:57:07.000000000 +0000 @@ -8,7 +8,7 @@ --- ableton-link.orig/examples/CMakeLists.txt +++ ableton-link/examples/CMakeLists.txt @@ -1,5 +1,6 @@ - cmake_minimum_required(VERSION 3.0) + cmake_minimum_required(VERSION 3.5) project(LinkExamples) +find_package(AbletonLink) diff -Nru ableton-link-3.0.6+dfsg/debian/patches/kfreebsd_hurd.patch ableton-link-3.1.1+dfsg/debian/patches/kfreebsd_hurd.patch --- ableton-link-3.0.6+dfsg/debian/patches/kfreebsd_hurd.patch 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/kfreebsd_hurd.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Description: treat kFreeBSD and the hurd the same as LINUX -Author: umlaeute -Origin: Debian -Forwarded: https://github.com/Ableton/link/pull/103 -Last-Update: 2021-09-10 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- ableton-link.orig/include/ableton/platforms/linux/Clock.hpp -+++ ableton-link/include/ableton/platforms/linux/Clock.hpp -@@ -36,6 +36,10 @@ - #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC - #endif - -+#if defined(__FreeBSD_kernel__) -+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC -+#endif -+ - namespace linux - { - diff -Nru ableton-link-3.0.6+dfsg/debian/patches/libatomic.patch ableton-link-3.1.1+dfsg/debian/patches/libatomic.patch --- ableton-link-3.0.6+dfsg/debian/patches/libatomic.patch 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/libatomic.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Description: Fix cmake snippet to link against libatomic - so it can be used on armel,... -Author: IOhannes m zmölnig -Origin: Debian -Bug: https://github.com/Ableton/link/issues/129 -Last-Update: 2023-01-12 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- ableton-link.orig/AbletonLinkConfig.cmake -+++ ableton-link/AbletonLinkConfig.cmake -@@ -40,12 +40,12 @@ - INTERFACE_LINK_LIBRARIES - pthread - ) -- if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) -+ #if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) - set_property(TARGET Ableton::Link APPEND PROPERTY - INTERFACE_LINK_LIBRARIES - atomic - ) -- endif() -+ #endif() - endif() - - include(${CMAKE_CURRENT_LIST_DIR}/cmake_include/AsioStandaloneConfig.cmake) diff -Nru ableton-link-3.0.6+dfsg/debian/patches/nocheck.patch ableton-link-3.1.1+dfsg/debian/patches/nocheck.patch --- ableton-link-3.0.6+dfsg/debian/patches/nocheck.patch 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/nocheck.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -Description: Allow disabling the building of tests - E.g. when using the 'nocheck' profile -Author: IOhannes m zmölnig -Origin: Debian -Bug: https://github.com/Ableton/link/issues/128 -Last-Update: 2023-01-10 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- ableton-link.orig/CMakeLists.txt -+++ ableton-link/CMakeLists.txt -@@ -22,6 +22,8 @@ - option(LINK_BUILD_VLD "Build with VLD support (VLD must be installed separately)" OFF) - endif() - -+option(LINK_BUILD_TESTS "Build unit test binaries" ON) -+ - # ____ _ _ - # | _ \ __ _| |_| |__ ___ - # | |_) / _` | __| '_ \/ __| -@@ -36,7 +38,9 @@ - include(extensions/abl_link/abl_link.cmake) - - add_subdirectory(include) -+if(LINK_BUILD_TESTS) - add_subdirectory(src) -+endif() - add_subdirectory(examples) - add_subdirectory(extensions/abl_link) - diff -Nru ableton-link-3.0.6+dfsg/debian/patches/series ableton-link-3.1.1+dfsg/debian/patches/series --- ableton-link-3.0.6+dfsg/debian/patches/series 2023-01-12 09:22:28.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/patches/series 2024-02-05 12:57:07.000000000 +0000 @@ -1,5 +1,3 @@ DEBIAN_system_libraries.patch -kfreebsd_hurd.patch +DEBIAN_catch3.patch examples.patch -nocheck.patch -libatomic.patch diff -Nru ableton-link-3.0.6+dfsg/debian/rules ableton-link-3.1.1+dfsg/debian/rules --- ableton-link-3.0.6+dfsg/debian/rules 2023-02-08 21:29:51.000000000 +0000 +++ ableton-link-3.1.1+dfsg/debian/rules 2024-03-02 18:24:26.000000000 +0000 @@ -14,8 +14,11 @@ ifneq ($(filter nocheck,$(DEB_BUILD_PROFILES)),) CONFIGURE_FLAGS += -DLINK_BUILD_TESTS=OFF +else +CONFIGURE_FLAGS += -DLINK_BUILD_TESTS=ON endif + # workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81358 ifneq (,$(filter $(DEB_HOST_ARCH), armel m68k mipsel powerpc riscv64 sh4)) export DEB_LDFLAGS_MAINT_APPEND += -Wl,--no-as-needed -latomic -Wl,--as-needed @@ -32,7 +35,7 @@ $(CONFIGURE_FLAGS) override_dh_install-indep: - dh_install --indep + dh_install -i find $(CURDIR)/debian/ableton-link-dev/usr/share -name "*.cmake" -exec \ sed -e 's|$${CMAKE_CURRENT_LIST_DIR}/include|/usr/include|g' -i {} + diff -Nru ableton-link-3.0.6+dfsg/examples/CMakeLists.txt ableton-link-3.1.1+dfsg/examples/CMakeLists.txt --- ableton-link-3.0.6+dfsg/examples/CMakeLists.txt 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/examples/CMakeLists.txt 2024-02-01 14:19:51.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) project(LinkExamples) # _ ____ ___ ___ diff -Nru ableton-link-3.0.6+dfsg/examples/esp32/dependencies.lock ableton-link-3.1.1+dfsg/examples/esp32/dependencies.lock --- ableton-link-3.0.6+dfsg/examples/esp32/dependencies.lock 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/examples/esp32/dependencies.lock 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,15 @@ +dependencies: + espressif/asio: + component_hash: 27069b3f640bb58e2cbceb6bc13dd8f791a2c11b38080543f1858b6104e45b98 + source: + service_url: https://api.components.espressif.com/ + type: service + version: 1.14.1~3 + idf: + component_hash: null + source: + type: idf + version: 5.1.1 +manifest_hash: 10a682a6641cabbc6127f743d9e310d694820bf50bb2627e140bb20ba4a940e0 +target: esp32 +version: 1.0.0 diff -Nru ableton-link-3.0.6+dfsg/examples/esp32/main/idf_component.yml ableton-link-3.1.1+dfsg/examples/esp32/main/idf_component.yml --- ableton-link-3.0.6+dfsg/examples/esp32/main/idf_component.yml 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/examples/esp32/main/idf_component.yml 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,17 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/asio: "*" + ## Required IDF version + idf: + version: ">=4.1.0" + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true diff -Nru ableton-link-3.0.6+dfsg/examples/esp32/main/main.cpp ableton-link-3.1.1+dfsg/examples/esp32/main/main.cpp --- ableton-link-3.0.6+dfsg/examples/esp32/main/main.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/examples/esp32/main/main.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -21,38 +21,6 @@ return nullptr; } -void IRAM_ATTR timer_group0_isr(void* userParam) -{ - static BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - TIMERG0.int_clr_timers.t0 = 1; - TIMERG0.hw_timer[0].config.alarm_en = 1; - - xSemaphoreGiveFromISR(userParam, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken) - { - portYIELD_FROM_ISR(); - } -} - -void timerGroup0Init(int timerPeriodUS, void* userParam) -{ - timer_config_t config = {.alarm_en = TIMER_ALARM_EN, - .counter_en = TIMER_PAUSE, - .intr_type = TIMER_INTR_LEVEL, - .counter_dir = TIMER_COUNT_UP, - .auto_reload = TIMER_AUTORELOAD_EN, - .divider = 80}; - - timer_init(TIMER_GROUP_0, TIMER_0, &config); - timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); - timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, timerPeriodUS); - timer_enable_intr(TIMER_GROUP_0, TIMER_0); - timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer_group0_isr, userParam, 0, nullptr); - - timer_start(TIMER_GROUP_0, TIMER_0); -} - void printTask(void* userParam) { auto link = static_cast(userParam); @@ -73,7 +41,6 @@ void tickTask(void* userParam) { - SemaphoreHandle_t handle = static_cast(userParam); ableton::Link link(120.0f); link.enable(true); @@ -86,12 +53,10 @@ while (true) { - xSemaphoreTake(handle, portMAX_DELAY); - const auto state = link.captureAudioSessionState(); const auto phase = state.phaseAtTime(link.clock().micros(), 1.); gpio_set_level(LED, fmodf(phase, 1.) < 0.1); - portYIELD(); + vTaskDelay(1); } } @@ -102,8 +67,5 @@ ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(example_connect()); - SemaphoreHandle_t tickSemphr = xSemaphoreCreateBinary(); - timerGroup0Init(100, tickSemphr); - - xTaskCreate(tickTask, "tick", 8192, tickSemphr, configMAX_PRIORITIES - 1, nullptr); + xTaskCreate(tickTask, "tick", 8192, nullptr, configMAX_PRIORITIES - 1, nullptr); } diff -Nru ableton-link-3.0.6+dfsg/examples/esp32/sdkconfig.defaults ableton-link-3.1.1+dfsg/examples/esp32/sdkconfig.defaults --- ableton-link-3.0.6+dfsg/examples/esp32/sdkconfig.defaults 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/examples/esp32/sdkconfig.defaults 2024-02-01 14:19:51.000000000 +0000 @@ -1 +1,3 @@ CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y + diff -Nru ableton-link-3.0.6+dfsg/include/CMakeLists.txt ableton-link-3.1.1+dfsg/include/CMakeLists.txt --- ableton-link-3.0.6+dfsg/include/CMakeLists.txt 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/CMakeLists.txt 2024-02-01 14:19:51.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) project(LinkCore) # ____ @@ -19,6 +19,7 @@ ${link_core_DIR}/LinearRegression.hpp ${link_core_DIR}/Measurement.hpp ${link_core_DIR}/MeasurementEndpointV4.hpp + ${link_core_DIR}/MeasurementEndpointV6.hpp ${link_core_DIR}/MeasurementService.hpp ${link_core_DIR}/Median.hpp ${link_core_DIR}/NodeId.hpp @@ -49,8 +50,9 @@ set(link_discovery_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ableton/discovery) set(link_discovery_HEADERS + ${link_discovery_DIR}/AsioTypes.hpp ${link_discovery_DIR}/InterfaceScanner.hpp - ${link_discovery_DIR}/IpV4Interface.hpp + ${link_discovery_DIR}/IpInterface.hpp ${link_discovery_DIR}/MessageTypes.hpp ${link_discovery_DIR}/NetworkByteStreamSerializable.hpp ${link_discovery_DIR}/Payload.hpp @@ -77,7 +79,6 @@ ${link_platform_DIR}/asio/Context.hpp ${link_platform_DIR}/asio/LockFreeCallbackDispatcher.hpp ${link_platform_DIR}/asio/Socket.hpp - ${link_platform_DIR}/asio/Util.hpp ) if(ESP_PLATFORM) diff -Nru ableton-link-3.0.6+dfsg/include/ableton/Link.ipp ableton-link-3.1.1+dfsg/include/ableton/Link.ipp --- ableton-link-3.0.6+dfsg/include/ableton/Link.ipp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/Link.ipp 2024-02-01 14:19:51.000000000 +0000 @@ -225,19 +225,33 @@ forceBeatAtTime(beat, time, quantum); } -template -inline void BasicLink::SessionState::forceBeatAtTime( - const double beat, const std::chrono::microseconds time, const double quantum) +inline void forceBeatAtTimeImpl(link::Timeline& timeline, + const link::Beats beat, + const std::chrono::microseconds time, + const link::Beats quantum) { // There are two components to the beat adjustment: a phase shift // and a beat magnitude adjustment. - const auto curBeatAtTime = link::Beats{beatAtTime(time, quantum)}; - const auto closestInPhase = - link::closestPhaseMatch(curBeatAtTime, link::Beats{beat}, link::Beats{quantum}); - mState.timeline = shiftClientTimeline(mState.timeline, closestInPhase - curBeatAtTime); + const auto curBeatAtTime = link::toPhaseEncodedBeats(timeline, time, quantum); + const auto closestInPhase = link::closestPhaseMatch(curBeatAtTime, beat, quantum); + timeline = shiftClientTimeline(timeline, closestInPhase - curBeatAtTime); // Now adjust the magnitude - mState.timeline.beatOrigin = - mState.timeline.beatOrigin + (link::Beats{beat} - closestInPhase); + timeline.beatOrigin = timeline.beatOrigin + beat - closestInPhase; +} + +template +inline void BasicLink::SessionState::forceBeatAtTime( + const double beat, std::chrono::microseconds time, const double quantum) +{ + forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, time, link::Beats{quantum}); + + // Due to quantization errors the resulting BeatTime at 'time' after forcing can be + // bigger than 'beat' which then violates intended behavior of the API and can lead + // i.e. to missing a downbeat. Thus we have to shift the timeline forwards. + if (beatAtTime(time, quantum) > beat) + { + forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, ++time, link::Beats{quantum}); + } } template diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/AsioTypes.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/AsioTypes.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/AsioTypes.hpp 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/AsioTypes.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,54 @@ +/* Copyright 2023, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#pragma once + +#include + +namespace ableton +{ +namespace discovery +{ + +using IpAddress = LINK_ASIO_NAMESPACE::ip::address; +using IpAddressV4 = LINK_ASIO_NAMESPACE::ip::address_v4; +using IpAddressV6 = LINK_ASIO_NAMESPACE::ip::address_v6; +using UdpSocket = LINK_ASIO_NAMESPACE::ip::udp::socket; +using UdpEndpoint = LINK_ASIO_NAMESPACE::ip::udp::endpoint; + +template +AsioAddrType makeAddress(const char* pAddr) +{ + using namespace std; + typename AsioAddrType::bytes_type bytes; + copy(pAddr, pAddr + bytes.size(), begin(bytes)); + return AsioAddrType{bytes}; +} + +template +AsioAddrType makeAddress(const char* pAddr, uint32_t scopeId) +{ + using namespace std; + typename AsioAddrType::bytes_type bytes; + copy(pAddr, pAddr + bytes.size(), begin(bytes)); + return AsioAddrType{bytes, scopeId}; +} + +} // namespace discovery +} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/InterfaceScanner.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/InterfaceScanner.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/InterfaceScanner.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/InterfaceScanner.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include #include @@ -29,7 +29,7 @@ namespace discovery { -// Callback takes a range of asio::ip:address which is +// Callback takes a range of IpAddress which is // guaranteed to be sorted and unique template class InterfaceScanner @@ -64,7 +64,7 @@ using namespace std; debug(mIo->log()) << "Scanning network interfaces"; // Rescan the hardware for available network interface addresses - vector addrs = mIo->scanNetworkInterfaces(); + vector addrs = mIo->scanNetworkInterfaces(); // Sort and unique them to guarantee consistent comparison sort(begin(addrs), end(addrs)); addrs.erase(unique(begin(addrs), end(addrs)), end(addrs)); diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/IpInterface.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/IpInterface.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/IpInterface.hpp 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/IpInterface.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,130 @@ +/* Copyright 2016, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#pragma once + +#include +#include + +namespace ableton +{ +namespace discovery +{ + +inline UdpEndpoint multicastEndpointV4() +{ + return {IpAddressV4::from_string("224.76.78.75"), 20808}; +} + +inline UdpEndpoint multicastEndpointV6(uint64_t scopeId) +{ + // This is a non-permanently-assigned link-local multicast address (RFC4291) + return { + ::LINK_ASIO_NAMESPACE::ip::make_address("ff12::8080%" + std::to_string(scopeId)), + 20808}; +} + +// Type tags for dispatching between unicast and multicast packets +struct MulticastTag +{ +}; +struct UnicastTag +{ +}; + +template +class IpInterface +{ +public: + using Socket = typename util::Injected::type::template Socket; + + IpInterface(util::Injected io, const IpAddress& addr) + : mIo(std::move(io)) + , mMulticastReceiveSocket(mIo->template openMulticastSocket(addr)) + , mSendSocket(mIo->template openUnicastSocket(addr)) + { + } + + IpInterface(const IpInterface&) = delete; + IpInterface& operator=(const IpInterface&) = delete; + + IpInterface(IpInterface&& rhs) + : mIo(std::move(rhs.mIo)) + , mMulticastReceiveSocket(std::move(rhs.mMulticastReceiveSocket)) + , mSendSocket(std::move(rhs.mSendSocket)) + { + } + + + std::size_t send( + const uint8_t* const pData, const size_t numBytes, const UdpEndpoint& to) + { + return mSendSocket.send(pData, numBytes, to); + } + + template + void receive(Handler handler, UnicastTag) + { + mSendSocket.receive(SocketReceiver{std::move(handler)}); + } + + template + void receive(Handler handler, MulticastTag) + { + mMulticastReceiveSocket.receive( + SocketReceiver(std::move(handler))); + } + + UdpEndpoint endpoint() const + { + return mSendSocket.endpoint(); + } + +private: + template + struct SocketReceiver + { + SocketReceiver(Handler handler) + : mHandler(std::move(handler)) + { + } + + template + void operator()(const UdpEndpoint& from, const It messageBegin, const It messageEnd) + { + mHandler(Tag{}, from, messageBegin, messageEnd); + } + + Handler mHandler; + }; + + util::Injected mIo; + Socket mMulticastReceiveSocket; + Socket mSendSocket; +}; + +template +IpInterface makeIpInterface( + util::Injected io, const IpAddress& addr) +{ + return {std::move(io), addr}; +} + +} // namespace discovery +} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/IpV4Interface.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/IpV4Interface.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/IpV4Interface.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/IpV4Interface.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -/* Copyright 2016, Ableton AG, Berlin. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * If you would like to incorporate Link into a proprietary software application, - * please contact . - */ - -#pragma once - -#include -#include - -namespace ableton -{ -namespace discovery -{ - -inline asio::ip::udp::endpoint multicastEndpoint() -{ - return {asio::ip::address_v4::from_string("224.76.78.75"), 20808}; -} - -// Type tags for dispatching between unicast and multicast packets -struct MulticastTag -{ -}; -struct UnicastTag -{ -}; - -template -class IpV4Interface -{ -public: - using Socket = typename util::Injected::type::template Socket; - - IpV4Interface(util::Injected io, const asio::ip::address_v4& addr) - : mIo(std::move(io)) - , mMulticastReceiveSocket(mIo->template openMulticastSocket(addr)) - , mSendSocket(mIo->template openUnicastSocket(addr)) - { - } - - IpV4Interface(const IpV4Interface&) = delete; - IpV4Interface& operator=(const IpV4Interface&) = delete; - - IpV4Interface(IpV4Interface&& rhs) - : mIo(std::move(rhs.mIo)) - , mMulticastReceiveSocket(std::move(rhs.mMulticastReceiveSocket)) - , mSendSocket(std::move(rhs.mSendSocket)) - { - } - - - std::size_t send( - const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to) - { - return mSendSocket.send(pData, numBytes, to); - } - - template - void receive(Handler handler, UnicastTag) - { - mSendSocket.receive(SocketReceiver{std::move(handler)}); - } - - template - void receive(Handler handler, MulticastTag) - { - mMulticastReceiveSocket.receive( - SocketReceiver(std::move(handler))); - } - - asio::ip::udp::endpoint endpoint() const - { - return mSendSocket.endpoint(); - } - -private: - template - struct SocketReceiver - { - SocketReceiver(Handler handler) - : mHandler(std::move(handler)) - { - } - - template - void operator()( - const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd) - { - mHandler(Tag{}, from, messageBegin, messageEnd); - } - - Handler mHandler; - }; - - util::Injected mIo; - Socket mMulticastReceiveSocket; - Socket mSendSocket; -}; - -template -IpV4Interface makeIpV4Interface( - util::Injected io, const asio::ip::address_v4& addr) -{ - return {std::move(io), addr}; -} - -} // namespace discovery -} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/NetworkByteStreamSerializable.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/NetworkByteStreamSerializable.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/NetworkByteStreamSerializable.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/NetworkByteStreamSerializable.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #if defined(LINK_PLATFORM_MACOSX) #include #elif defined(LINK_PLATFORM_LINUX) diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/Payload.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/Payload.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/Payload.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/Payload.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -82,6 +82,11 @@ template friend It toNetworkByteStream(const PayloadEntry& entry, It out) { + // Don't serialize Entry if its value is of size zero + if (sizeInByteStream(entry.value) == 0) + { + return out; + } return toNetworkByteStream( entry.value, toNetworkByteStream(entry.header, std::move(out))); } diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/PeerGateway.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/PeerGateway.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/PeerGateway.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/PeerGateway.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -216,7 +216,7 @@ // IpV4 gateway types template using IpV4Messenger = UdpMessenger< - IpV4Interface::type&, v1::kMaxMessageSize>, + IpInterface::type&, v1::kMaxMessageSize>, StateQuery, IoContext>; @@ -226,11 +226,11 @@ PeerObserver, IoContext>; -// Factory function to bind a PeerGateway to an IpV4Interface with the given address. +// Factory function to bind a PeerGateway to an IpInterface with the given address. template IpV4Gateway makeIpV4Gateway( util::Injected io, - const asio::ip::address_v4& addr, + const IpAddress& addr, util::Injected observer, NodeState state) { @@ -240,7 +240,7 @@ const uint8_t ttl = 5; const uint8_t ttlRatio = 20; - auto iface = makeIpV4Interface(injectRef(*io), addr); + auto iface = makeIpInterface(injectRef(*io), addr); auto messenger = makeUdpMessenger( injectVal(std::move(iface)), std::move(state), injectRef(*io), ttl, ttlRatio); diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/PeerGateways.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/PeerGateways.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/PeerGateways.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/PeerGateways.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,8 +19,8 @@ #pragma once +#include #include -#include #include namespace ableton @@ -28,7 +28,7 @@ namespace discovery { -// GatewayFactory must have an operator()(NodeState, IoRef, asio::ip::address) +// GatewayFactory must have an operator()(NodeState, IoRef, IpAddress) // that constructs a new PeerGateway on a given interface address. template class PeerGateways @@ -37,8 +37,8 @@ using IoType = typename util::Injected::type; using Gateway = decltype(std::declval()(std::declval(), std::declval>(), - std::declval())); - using GatewayMap = std::map; + std::declval())); + using GatewayMap = std::map; PeerGateways(const std::chrono::seconds rescanPeriod, NodeState state, @@ -87,7 +87,7 @@ // If a gateway has become non-responsive or is throwing exceptions, // this method can be invoked to either fix it or discard it. - void repairGateway(const asio::ip::address& gatewayAddr) + void repairGateway(const IpAddress& gatewayAddr) { if (mpScannerCallback->mGateways.erase(gatewayAddr)) { @@ -112,18 +112,18 @@ { using namespace std; // Get the set of current addresses. - vector curAddrs; + vector curAddrs; curAddrs.reserve(mGateways.size()); transform(std::begin(mGateways), std::end(mGateways), back_inserter(curAddrs), [](const typename GatewayMap::value_type& vt) { return vt.first; }); // Now use set_difference to determine the set of addresses that // are new and the set of cur addresses that are no longer there - vector newAddrs; + vector newAddrs; set_difference(std::begin(range), std::end(range), std::begin(curAddrs), std::end(curAddrs), back_inserter(newAddrs)); - vector staleAddrs; + vector staleAddrs; set_difference(std::begin(curAddrs), std::end(curAddrs), std::begin(range), std::end(range), back_inserter(staleAddrs)); @@ -138,12 +138,8 @@ { try { - // Only handle v4 for now - if (addr.is_v4()) - { - info(mIo.log()) << "initializing peer gateway on interface " << addr; - mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr.to_v4())); - } + info(mIo.log()) << "initializing peer gateway on interface " << addr; + mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr)); } catch (const runtime_error& e) { diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/Service.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/Service.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/Service.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/Service.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -59,7 +59,7 @@ // Repair the gateway with the given address if possible. Its // sockets may have been closed, for example, and the gateway needs // to be regenerated. - void repairGateway(const asio::ip::address& gatewayAddr) + void repairGateway(const IpAddress& gatewayAddr) { mGateways.repairGateway(gatewayAddr); } diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/UdpMessenger.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/UdpMessenger.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/UdpMessenger.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/UdpMessenger.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,10 +19,10 @@ #pragma once -#include +#include +#include #include #include -#include #include #include #include @@ -37,15 +37,23 @@ // interface through which the sending failed. struct UdpSendException : std::runtime_error { - UdpSendException(const std::runtime_error& e, asio::ip::address ifAddr) + UdpSendException(const std::runtime_error& e, IpAddress ifAddr) : std::runtime_error(e.what()) , interfaceAddr(std::move(ifAddr)) { } - asio::ip::address interfaceAddr; + IpAddress interfaceAddr; }; +template +UdpEndpoint ipV6Endpoint(Interface& iface, const UdpEndpoint& endpoint) +{ + auto v6Address = endpoint.address().to_v6(); + v6Address.scope_id(iface.endpoint().address().to_v6().scope_id()); + return {v6Address, endpoint.port()}; +} + // Throws UdpSendException template void sendUdpMessage(Interface& iface, @@ -53,7 +61,7 @@ const uint8_t ttl, const v1::MessageType messageType, const Payload& payload, - const asio::ip::udp::endpoint& to) + const UdpEndpoint& to) { using namespace std; v1::MessageBuffer buffer; @@ -176,8 +184,16 @@ void sendByeBye() { - sendUdpMessage( - *mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), multicastEndpoint()); + if (mInterface->endpoint().address().is_v4()) + { + sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), + multicastEndpointV4()); + } + if (mInterface->endpoint().address().is_v6()) + { + sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), + multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id())); + } } void updateState(NodeState state) @@ -213,21 +229,29 @@ if (delay < milliseconds{1}) { debug(mIo->log()) << "Broadcasting state"; - sendPeerState(v1::kAlive, multicastEndpoint()); + if (mInterface->endpoint().address().is_v4()) + { + sendPeerState(v1::kAlive, multicastEndpointV4()); + } + if (mInterface->endpoint().address().is_v6()) + { + sendPeerState(v1::kAlive, + multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id())); + } } } - void sendPeerState( - const v1::MessageType messageType, const asio::ip::udp::endpoint& to) + void sendPeerState(const v1::MessageType messageType, const UdpEndpoint& to) { sendUdpMessage( *mInterface, mState.ident(), mTtl, messageType, toPayload(mState), to); mLastBroadcastTime = mTimer.now(); } - void sendResponse(const asio::ip::udp::endpoint& to) + void sendResponse(const UdpEndpoint& to) { - sendPeerState(v1::kResponse, to); + const auto endpoint = to.address().is_v4() ? to : ipV6Endpoint(*mInterface, to); + sendPeerState(v1::kResponse, endpoint); } template @@ -237,10 +261,8 @@ } template - void operator()(Tag tag, - const asio::ip::udp::endpoint& from, - const It messageBegin, - const It messageEnd) + void operator()( + Tag tag, const UdpEndpoint& from, const It messageBegin, const It messageEnd) { auto result = v1::parseMessageHeader(messageBegin, messageEnd); diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/test/Interface.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/test/Interface.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/test/Interface.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/test/Interface.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -31,9 +31,8 @@ class Interface { public: - void send(const uint8_t* const bytes, - const size_t numBytes, - const asio::ip::udp::endpoint& endpoint) + void send( + const uint8_t* const bytes, const size_t numBytes, const UdpEndpoint& endpoint) { sentMessages.push_back( std::make_pair(std::vector{bytes, bytes + numBytes}, endpoint)); @@ -42,31 +41,30 @@ template void receive(Callback callback, Tag tag) { - mCallback = [callback, tag](const asio::ip::udp::endpoint& from, - const std::vector& buffer) { + mCallback = [callback, tag]( + const UdpEndpoint& from, const std::vector& buffer) { callback(tag, from, begin(buffer), end(buffer)); }; } template - void incomingMessage( - const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd) + void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd) { std::vector buffer{messageBegin, messageEnd}; mCallback(from, buffer); } - asio::ip::udp::endpoint endpoint() const + UdpEndpoint endpoint() const { - return asio::ip::udp::endpoint({}, 0); + return UdpEndpoint({}, 0); } - using SentMessage = std::pair, asio::ip::udp::endpoint>; + using SentMessage = std::pair, UdpEndpoint>; std::vector sentMessages; private: using ReceiveCallback = - std::function&)>; + std::function&)>; ReceiveCallback mCallback; }; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/discovery/test/Socket.hpp ableton-link-3.1.1+dfsg/include/ableton/discovery/test/Socket.hpp --- ableton-link-3.0.6+dfsg/include/ableton/discovery/test/Socket.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/discovery/test/Socket.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include @@ -37,12 +37,12 @@ { } - friend void configureUnicastSocket(Socket&, const asio::ip::address_v4&) + friend void configureUnicastSocket(Socket&, const IpAddressV4&) { } std::size_t send( - const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to) + const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to) { sentMessages.push_back( std::make_pair(std::vector{pData, pData + numBytes}, to)); @@ -52,31 +52,29 @@ template void receive(Handler handler) { - mCallback = [handler](const asio::ip::udp::endpoint& from, - const std::vector& buffer) { + mCallback = [handler](const UdpEndpoint& from, const std::vector& buffer) { handler(from, begin(buffer), end(buffer)); }; } template - void incomingMessage( - const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd) + void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd) { std::vector buffer{messageBegin, messageEnd}; mCallback(from, buffer); } - asio::ip::udp::endpoint endpoint() const + UdpEndpoint endpoint() const { - return asio::ip::udp::endpoint({}, 0); + return UdpEndpoint({}, 0); } - using SentMessage = std::pair, asio::ip::udp::endpoint>; + using SentMessage = std::pair, UdpEndpoint>; std::vector sentMessages; private: using ReceiveCallback = - std::function&)>; + std::function&)>; ReceiveCallback mCallback; }; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/Controller.hpp ableton-link-3.1.1+dfsg/include/ableton/link/Controller.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/Controller.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/Controller.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -717,18 +717,11 @@ { GatewayPtr operator()(std::pair state, util::Injected io, - const asio::ip::address& addr) + const discovery::IpAddress& addr) { - if (addr.is_v4()) - { - return GatewayPtr{new ControllerGateway{std::move(io), addr.to_v4(), - util::injectVal(makeGatewayObserver(mController.mPeers, addr)), - std::move(state.first), std::move(state.second), mController.mClock}}; - } - else - { - throw std::runtime_error("Could not create peer gateway on non-ipV4 address"); - } + return GatewayPtr{new ControllerGateway{std::move(io), addr, + util::injectVal(makeGatewayObserver(mController.mPeers, addr)), + std::move(state.first), std::move(state.second), mController.mClock}}; } Controller& mController; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/Gateway.hpp ableton-link-3.1.1+dfsg/include/ableton/link/Gateway.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/Gateway.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/Gateway.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -33,7 +33,7 @@ { public: Gateway(util::Injected io, - asio::ip::address_v4 addr, + discovery::IpAddress addr, util::Injected observer, NodeState nodeState, GhostXForm ghostXForm, diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/Measurement.hpp ableton-link-3.1.1+dfsg/include/ableton/link/Measurement.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/Measurement.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/Measurement.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -45,7 +45,7 @@ Measurement(const PeerState& state, Callback callback, - asio::ip::address_v4 address, + discovery::IpAddress address, Clock clock, util::Injected io) : mIo(std::move(io)) @@ -69,12 +69,11 @@ Impl(const PeerState& state, Callback callback, - asio::ip::address_v4 address, + discovery::IpAddress address, Clock clock, util::Injected io) : mSocket(io->template openUnicastSocket(address)) , mSessionId(state.nodeState.sessionId) - , mEndpoint(state.endpoint) , mCallback(std::move(callback)) , mClock(std::move(clock)) , mTimer(io->makeTimer()) @@ -82,6 +81,17 @@ , mLog(channel(io->log(), "Measurement on gateway@" + address.to_string())) , mSuccess(false) { + if (state.endpoint.address().is_v4()) + { + mEndpoint = state.endpoint; + } + else + { + auto v6Address = state.endpoint.address().to_v6(); + v6Address.scope_id(address.to_v6().scope_id()); + mEndpoint = {v6Address, state.endpoint.port()}; + } + const auto ht = HostTime{mClock.micros()}; sendPing(mEndpoint, discovery::makePayload(ht)); resetTimer(); @@ -117,7 +127,7 @@ // Operator to handle incoming messages on the interface template void operator()( - const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd) + const discovery::UdpEndpoint& from, const It messageBegin, const It messageEnd) { using namespace std; const auto result = v1::parseMessageHeader(messageBegin, messageEnd); @@ -197,7 +207,7 @@ } template - void sendPing(asio::ip::udp::endpoint to, const Payload& payload) + void sendPing(discovery::UdpEndpoint to, const Payload& payload) { v1::MessageBuffer buffer; const auto msgBegin = std::begin(buffer); @@ -232,7 +242,7 @@ Socket mSocket; SessionId mSessionId; - asio::ip::udp::endpoint mEndpoint; + discovery::UdpEndpoint mEndpoint; std::vector mData; Callback mCallback; Clock mClock; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementEndpointV4.hpp ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementEndpointV4.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementEndpointV4.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementEndpointV4.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,8 +19,9 @@ #pragma once +#include #include -#include +#include namespace ableton { @@ -35,6 +36,10 @@ // Model the NetworkByteStreamSerializable concept friend std::uint32_t sizeInByteStream(const MeasurementEndpointV4 mep) { + if (mep.ep.address().is_v6()) + { + return 0; + } return discovery::sizeInByteStream( static_cast(mep.ep.address().to_v4().to_ulong())) + discovery::sizeInByteStream(mep.ep.port()); @@ -43,6 +48,7 @@ template friend It toNetworkByteStream(const MeasurementEndpointV4 mep, It out) { + assert(mep.ep.address().is_v4()); return discovery::toNetworkByteStream(mep.ep.port(), discovery::toNetworkByteStream( static_cast(mep.ep.address().to_v4().to_ulong()), std::move(out))); @@ -58,11 +64,11 @@ std::move(addrRes.second), end); return make_pair( MeasurementEndpointV4{ - {asio::ip::address_v4{std::move(addrRes.first)}, std::move(portRes.first)}}, + {discovery::IpAddressV4{std::move(addrRes.first)}, std::move(portRes.first)}}, std::move(portRes.second)); } - asio::ip::udp::endpoint ep; + discovery::UdpEndpoint ep; }; } // namespace link diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementEndpointV6.hpp ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementEndpointV6.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementEndpointV6.hpp 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementEndpointV6.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,75 @@ +/* Copyright 2023, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#pragma once + +#include +#include +#include + +namespace ableton +{ +namespace link +{ + +struct MeasurementEndpointV6 +{ + static const std::int32_t key = 'mep6'; + static_assert(key == 0x6d657036, "Unexpected byte order"); + + // Model the NetworkByteStreamSerializable concept + friend std::uint32_t sizeInByteStream(const MeasurementEndpointV6 mep) + { + if (mep.ep.address().is_v4()) + { + return 0; + } + return discovery::sizeInByteStream(mep.ep.address().to_v6().to_bytes()) + + discovery::sizeInByteStream(mep.ep.port()); + } + + template + friend It toNetworkByteStream(const MeasurementEndpointV6 mep, It out) + { + assert(mep.ep.address().is_v6()); + return discovery::toNetworkByteStream( + mep.ep.port(), discovery::toNetworkByteStream( + mep.ep.address().to_v6().to_bytes(), std::move(out))); + } + + template + static std::pair fromNetworkByteStream(It begin, It end) + { + using namespace std; + auto addrRes = + discovery::Deserialize::fromNetworkByteStream( + std::move(begin), end); + auto portRes = discovery::Deserialize::fromNetworkByteStream( + std::move(addrRes.second), end); + return make_pair( + MeasurementEndpointV6{ + {discovery::IpAddressV6{std::move(addrRes.first)}, std::move(portRes.first)}}, + std::move(portRes.second)); + } + + discovery::UdpEndpoint ep; +}; + +} // namespace link +} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementService.hpp ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementService.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/MeasurementService.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/MeasurementService.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -42,7 +42,7 @@ using IoType = util::Injected; using MeasurementInstance = Measurement; - MeasurementService(asio::ip::address_v4 address, + MeasurementService(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock, @@ -65,7 +65,7 @@ mPingResponder.updateNodeState(sessionId, xform); } - asio::ip::udp::endpoint endpoint() const + discovery::UdpEndpoint endpoint() const { return mPingResponder.endpoint(); } @@ -77,7 +77,7 @@ using namespace std; const auto nodeId = state.nodeState.nodeId; - auto addr = mPingResponder.endpoint().address().to_v4(); + auto addr = mPingResponder.endpoint().address(); auto callback = CompletionCallback{*this, nodeId, handler}; try diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/PeerState.hpp ableton-link-3.1.1+dfsg/include/ableton/link/PeerState.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/PeerState.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/PeerState.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include #include namespace ableton @@ -61,12 +62,16 @@ return lhs.nodeState == rhs.nodeState && lhs.endpoint == rhs.endpoint; } - friend auto toPayload(const PeerState& state) - -> decltype(std::declval() - + discovery::makePayload(MeasurementEndpointV4{{}})) - { + friend auto toPayload(const PeerState& state) -> decltype( + std::declval() + discovery::makePayload(MeasurementEndpointV4{{}}) + + discovery::makePayload(MeasurementEndpointV6{{}})) + { + // This implements a switch if either an IPv4 or IPv6 endpoint is serialized. + // MeasurementEndpoints that contain an endpoint that does not match the IP protocol + // version return a sizeInByteStream() of zero and won't be serialized. return toPayload(state.nodeState) - + discovery::makePayload(MeasurementEndpointV4{state.endpoint}); + + discovery::makePayload(MeasurementEndpointV4{state.endpoint}) + + discovery::makePayload(MeasurementEndpointV6{state.endpoint}); } template @@ -75,15 +80,16 @@ using namespace std; auto peerState = PeerState{NodeState::fromPayload(std::move(id), begin, end), {}}; - discovery::parsePayload( - std::move(begin), std::move(end), [&peerState](MeasurementEndpointV4 me4) { - peerState.endpoint = std::move(me4.ep); - }); + discovery::parsePayload( + std::move(begin), std::move(end), + [&peerState](MeasurementEndpointV4 me4) { peerState.endpoint = std::move(me4.ep); }, + [&peerState]( + MeasurementEndpointV6 me6) { peerState.endpoint = std::move(me6.ep); }); return peerState; } NodeState nodeState; - asio::ip::udp::endpoint endpoint; + discovery::UdpEndpoint endpoint; }; } // namespace link diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/Peers.hpp ableton-link-3.1.1+dfsg/include/ableton/link/Peers.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/Peers.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/Peers.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -47,7 +47,7 @@ struct Impl; public: - using Peer = std::pair; + using Peer = std::pair; Peers(util::Injected io, SessionMembershipCallback membership, @@ -119,7 +119,7 @@ using GatewayObserverNodeState = PeerState; using GatewayObserverNodeId = NodeId; - GatewayObserver(std::shared_ptr pImpl, asio::ip::address addr) + GatewayObserver(std::shared_ptr pImpl, discovery::IpAddress addr) : mpImpl(std::move(pImpl)) , mAddr(std::move(addr)) { @@ -165,11 +165,11 @@ } std::shared_ptr mpImpl; - asio::ip::address mAddr; + discovery::IpAddress mAddr; }; // Factory function for the gateway observer - friend GatewayObserver makeGatewayObserver(Peers& peers, asio::ip::address addr) + friend GatewayObserver makeGatewayObserver(Peers& peers, discovery::IpAddress addr) { return GatewayObserver{peers.mpImpl, std::move(addr)}; } @@ -188,7 +188,7 @@ { } - void sawPeerOnGateway(PeerState peerState, asio::ip::address gatewayAddr) + void sawPeerOnGateway(PeerState peerState, discovery::IpAddress gatewayAddr) { using namespace std; @@ -255,7 +255,7 @@ } } - void peerLeftGateway(const NodeId& nodeId, const asio::ip::address& gatewayAddr) + void peerLeftGateway(const NodeId& nodeId, const discovery::IpAddress& gatewayAddr) { using namespace std; @@ -276,7 +276,7 @@ } } - void gatewayClosed(const asio::ip::address& gatewayAddr) + void gatewayClosed(const discovery::IpAddress& gatewayAddr) { using namespace std; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/link/PingResponder.hpp ableton-link-3.1.1+dfsg/include/ableton/link/PingResponder.hpp --- ableton-link-3.0.6+dfsg/include/ableton/link/PingResponder.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/link/PingResponder.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -40,7 +40,7 @@ using Socket = typename IoType::type::template Socket; public: - PingResponder(asio::ip::address_v4 address, + PingResponder(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock, @@ -64,12 +64,12 @@ mpImpl->mGhostXForm = std::move(xform); } - asio::ip::udp::endpoint endpoint() const + discovery::UdpEndpoint endpoint() const { return mpImpl->mSocket.endpoint(); } - asio::ip::address address() const + discovery::IpAddress address() const { return endpoint().address(); } @@ -82,7 +82,7 @@ private: struct Impl : std::enable_shared_from_this { - Impl(asio::ip::address_v4 address, + Impl(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock, @@ -102,7 +102,7 @@ // Operator to handle incoming messages on the interface template - void operator()(const asio::ip::udp::endpoint& from, const It begin, const It end) + void operator()(const discovery::UdpEndpoint& from, const It begin, const It end) { using namespace discovery; @@ -136,7 +136,7 @@ } template - void reply(It begin, It end, const asio::ip::udp::endpoint& to) + void reply(It begin, It end, const discovery::UdpEndpoint& to) { using namespace discovery; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/Config.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/Config.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/Config.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/Config.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -62,31 +62,33 @@ using Clock = platforms::windows::Clock; using Random = platforms::stl::Random; #if defined(LINK_WINDOWS_SETTHREADDESCRIPTION) -using IoContext = platforms::asio::Context; +using IoContext = + platforms::LINK_ASIO_NAMESPACE::Context; #else using IoContext = - platforms::asio::Context; + platforms::LINK_ASIO_NAMESPACE::Context; #endif #elif defined(LINK_PLATFORM_MACOSX) using Clock = platforms::darwin::Clock; -using IoContext = platforms::asio::Context; using Random = platforms::stl::Random; #elif defined(LINK_PLATFORM_LINUX) -using Clock = platforms::linux::ClockMonotonicRaw; +using Clock = platforms::linux_::ClockMonotonicRaw; using Random = platforms::stl::Random; #ifdef __linux__ -using IoContext = platforms::asio::Context; + platforms::linux_::ThreadFactory>; #else using IoContext = - platforms::asio::Context; + platforms::LINK_ASIO_NAMESPACE::Context; #endif #elif defined(ESP_PLATFORM) diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/AsioTimer.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/AsioTimer.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/AsioTimer.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/AsioTimer.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -27,7 +27,7 @@ { namespace platforms { -namespace asio +namespace LINK_ASIO_NAMESPACE { // This implementation is based on the boost::asio::system_timer concept. @@ -41,11 +41,14 @@ class AsioTimer { public: - using ErrorCode = ::asio::error_code; + using ErrorCode = ::LINK_ASIO_NAMESPACE::error_code; using TimePoint = std::chrono::system_clock::time_point; + using IoService = ::LINK_ASIO_NAMESPACE::io_service; + using SystemTimer = ::LINK_ASIO_NAMESPACE::system_timer; - AsioTimer(::asio::io_service& io) - : mpTimer(new ::asio::system_timer(io)) + + AsioTimer(IoService& io) + : mpTimer(new SystemTimer(io)) , mpAsyncHandler(std::make_shared()) { } @@ -123,10 +126,10 @@ std::function mpHandler; }; - std::unique_ptr<::asio::system_timer> mpTimer; + std::unique_ptr mpTimer; std::shared_ptr mpAsyncHandler; }; -} // namespace asio +} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/AsioWrapper.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/AsioWrapper.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/AsioWrapper.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/AsioWrapper.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -26,12 +26,19 @@ * by Link. */ -#if !defined(ESP_PLATFORM) +#if defined(ESP_PLATFORM) + +#define LINK_ASIO_NAMESPACE asio + +#else + #pragma push_macro("ASIO_STANDALONE") -#define ASIO_STANDALONE 1 #pragma push_macro("ASIO_NO_TYPEID") #define ASIO_NO_TYPEID 1 +#define asio link_asio_1_28_0 +#define LINK_ASIO_NAMESPACE link_asio_1_28_0 +#define ASIO_STANDALONE 1 #endif #if defined(LINK_PLATFORM_WINDOWS) @@ -75,11 +82,6 @@ #pragma pop_macro("INCL_EXTRA_HTON_FUNCTIONS") #endif -#if !defined(ESP_PLATFORM) -#pragma pop_macro("ASIO_STANDALONE") -#pragma pop_macro("ASIO_NO_TYPEID") -#endif - #if defined(_MSC_VER) #pragma warning(pop) #undef _SCL_SECURE_NO_WARNINGS @@ -88,3 +90,5 @@ #if defined(__clang__) #pragma clang diagnostic pop #endif + +#undef asio diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Context.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Context.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Context.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Context.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,9 +19,8 @@ #pragma once -#include +#include #include -#include #include #include #include @@ -31,7 +30,7 @@ { namespace platforms { -namespace asio +namespace LINK_ASIO_NAMESPACE { namespace { @@ -51,7 +50,7 @@ class Context { public: - using Timer = AsioTimer; + using Timer = LINK_ASIO_NAMESPACE::AsioTimer; using Log = LogT; template @@ -59,7 +58,9 @@ LockFreeCallbackDispatcher; template - using Socket = asio::Socket; + using Socket = Socket; + using IoService = ::LINK_ASIO_NAMESPACE::io_service; + using Work = IoService::work; Context() : Context(DefaultHandler{}) @@ -68,11 +69,11 @@ template explicit Context(ExceptionHandler exceptHandler) - : mpService(new ::asio::io_service()) - , mpWork(new ::asio::io_service::work(*mpService)) + : mpService(new IoService()) + , mpWork(new Work(*mpService)) { mThread = ThreadFactoryT::makeThread("Link Main", - [](::asio::io_service& service, ExceptionHandler handler) { + [](IoService& service, ExceptionHandler handler) { for (;;) { try @@ -121,34 +122,79 @@ template - Socket openUnicastSocket(const ::asio::ip::address_v4& addr) + Socket openUnicastSocket(const discovery::IpAddress addr) { - auto socket = Socket{*mpService}; + auto socket = + addr.is_v4() ? Socket{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()} + : Socket{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()}; socket.mpImpl->mSocket.set_option( - ::asio::ip::multicast::enable_loopback(addr.is_loopback())); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr)); - socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0}); + ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback())); + if (addr.is_v4()) + { + socket.mpImpl->mSocket.set_option( + ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4())); + socket.mpImpl->mSocket.bind( + ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0}); + } + else if (addr.is_v6()) + { + const auto scopeId = addr.to_v6().scope_id(); + socket.mpImpl->mSocket.set_option( + ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface( + static_cast(scopeId))); + socket.mpImpl->mSocket.bind( + ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0}); + } + else + { + throw(std::runtime_error("Unknown Protocol")); + } return socket; } template - Socket openMulticastSocket(const ::asio::ip::address_v4& addr) + Socket openMulticastSocket(const discovery::IpAddress& addr) { - auto socket = Socket{*mpService}; - socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true)); + auto socket = + addr.is_v4() ? Socket{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()} + : Socket{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()}; + + socket.mpImpl->mSocket.set_option( + ::LINK_ASIO_NAMESPACE::ip::udp::socket::reuse_address(true)); socket.mpImpl->mSocket.set_option( - ::asio::socket_base::broadcast(!addr.is_loopback())); + ::LINK_ASIO_NAMESPACE::socket_base::broadcast(!addr.is_loopback())); socket.mpImpl->mSocket.set_option( - ::asio::ip::multicast::enable_loopback(addr.is_loopback())); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr)); - socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"), - discovery::multicastEndpoint().port()}); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group( - discovery::multicastEndpoint().address().to_v4(), addr)); + ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback())); + + if (addr.is_v4()) + { + socket.mpImpl->mSocket.set_option( + ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4())); + socket.mpImpl->mSocket.bind({::LINK_ASIO_NAMESPACE::ip::address_v4::any(), + discovery::multicastEndpointV4().port()}); + socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group( + discovery::multicastEndpointV4().address().to_v4(), addr.to_v4())); + } + else if (addr.is_v6()) + { + const auto scopeId = addr.to_v6().scope_id(); + socket.mpImpl->mSocket.set_option( + ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface( + static_cast(scopeId))); + const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId); + socket.mpImpl->mSocket.bind( + {::LINK_ASIO_NAMESPACE::ip::address_v6::any(), multicastEndpoint.port()}); + socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group( + multicastEndpoint.address().to_v6(), scopeId)); + } + else + { + throw(std::runtime_error("Unknown Protocol")); + } return socket; } - std::vector<::asio::ip::address> scanNetworkInterfaces() + std::vector scanNetworkInterfaces() { return mScanIpIfAddrs(); } @@ -184,13 +230,13 @@ } }; - std::unique_ptr<::asio::io_service> mpService; - std::unique_ptr<::asio::io_service::work> mpWork; + std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service> mpService; + std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service::work> mpWork; std::thread mThread; Log mLog; ScanIpIfAddrs mScanIpIfAddrs; }; -} // namespace asio +} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -27,7 +27,7 @@ { namespace platforms { -namespace asio +namespace LINK_ASIO_NAMESPACE { // Utility to signal invocation of a callback on another thread in a lock free manner. @@ -83,6 +83,6 @@ std::thread mThread; }; -} // namespace asio +} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Socket.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Socket.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Socket.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Socket.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include #include @@ -28,14 +28,14 @@ { namespace platforms { -namespace asio +namespace LINK_ASIO_NAMESPACE { template struct Socket { - Socket(::asio::io_service& io) - : mpImpl(std::make_shared(io)) + Socket(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol) + : mpImpl(std::make_shared(io, protocol)) { } @@ -47,12 +47,11 @@ { } - std::size_t send(const uint8_t* const pData, - const size_t numBytes, - const ::asio::ip::udp::endpoint& to) + std::size_t send( + const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to) { assert(numBytes < MaxPacketSize); - return mpImpl->mSocket.send_to(::asio::buffer(pData, numBytes), to); + return mpImpl->mSocket.send_to(::LINK_ASIO_NAMESPACE::buffer(pData, numBytes), to); } template @@ -60,19 +59,19 @@ { mpImpl->mHandler = std::move(handler); mpImpl->mSocket.async_receive_from( - ::asio::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), mpImpl->mSenderEndpoint, - util::makeAsyncSafe(mpImpl)); + ::LINK_ASIO_NAMESPACE::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), + mpImpl->mSenderEndpoint, util::makeAsyncSafe(mpImpl)); } - ::asio::ip::udp::endpoint endpoint() const + discovery::UdpEndpoint endpoint() const { return mpImpl->mSocket.local_endpoint(); } struct Impl { - Impl(::asio::io_service& io) - : mSocket(io, ::asio::ip::udp::v4()) + Impl(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol) + : mSocket(io, protocol) { } @@ -80,12 +79,13 @@ { // Ignore error codes in shutdown and close as the socket may // have already been forcibly closed - ::asio::error_code ec; - mSocket.shutdown(::asio::ip::udp::socket::shutdown_both, ec); + ::LINK_ASIO_NAMESPACE::error_code ec; + mSocket.shutdown(::LINK_ASIO_NAMESPACE::ip::udp::socket::shutdown_both, ec); mSocket.close(ec); } - void operator()(const ::asio::error_code& error, const std::size_t numBytes) + void operator()( + const ::LINK_ASIO_NAMESPACE::error_code& error, const std::size_t numBytes) { if (!error && numBytes > 0 && numBytes <= MaxPacketSize) { @@ -94,17 +94,17 @@ } } - ::asio::ip::udp::socket mSocket; - ::asio::ip::udp::endpoint mSenderEndpoint; + discovery::UdpSocket mSocket; + discovery::UdpEndpoint mSenderEndpoint; using Buffer = std::array; Buffer mReceiveBuffer; using ByteIt = typename Buffer::const_iterator; - std::function mHandler; + std::function mHandler; }; std::shared_ptr mpImpl; }; -} // namespace asio +} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Util.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Util.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/asio/Util.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/asio/Util.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* Copyright 2016, Ableton AG, Berlin. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * If you would like to incorporate Link into a proprietary software application, - * please contact . - */ - -#pragma once - -#include - -namespace ableton -{ -namespace platforms -{ -namespace asio -{ - -// Utility for making v4 or v6 ip addresses from raw bytes in network byte-order -template -AsioAddrType makeAddress(const char* pAddr) -{ - using namespace std; - typename AsioAddrType::bytes_type bytes; - copy(pAddr, pAddr + bytes.size(), begin(bytes)); - return AsioAddrType{bytes}; -} - -} // namespace asio -} // namespace platforms -} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/darwin/Clock.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/darwin/Clock.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/darwin/Clock.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/darwin/Clock.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -49,6 +50,8 @@ Ticks microsToTicks(const Micros micros) const { + // Negative Micros can not be represented in Ticks + assert(micros.count() >= 0); return static_cast(micros.count() / mTicksToMicros); } diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/esp32/Context.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/esp32/Context.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/esp32/Context.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/esp32/Context.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,12 +19,12 @@ #pragma once -#include +#include +#include #include -#include #include #include -#include +#include #include #include @@ -40,7 +40,6 @@ { class ServiceRunner { - static void run(void* userParams) { auto runner = static_cast(userParams); @@ -60,11 +59,7 @@ static void IRAM_ATTR timerIsr(void* userParam) { static BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1); - timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_1); - - vTaskNotifyGiveFromISR(userParam, &xHigherPriorityTaskWoken); + vTaskNotifyGiveFromISR(*((TaskHandle_t*)userParam), &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); @@ -79,24 +74,21 @@ xTaskCreatePinnedToCore(run, "link", 8192, this, 2 | portPRIVILEGE_BIT, &mTaskHandle, LINK_ESP_TASK_CORE_ID); - timer_config_t config = {.alarm_en = TIMER_ALARM_EN, - .counter_en = TIMER_PAUSE, - .intr_type = TIMER_INTR_LEVEL, - .counter_dir = TIMER_COUNT_UP, - .auto_reload = TIMER_AUTORELOAD_EN, - .divider = 80}; - - timer_init(TIMER_GROUP_0, TIMER_1, &config); - timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0); - timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, 100); - timer_enable_intr(TIMER_GROUP_0, TIMER_1); - timer_isr_register(TIMER_GROUP_0, TIMER_1, &timerIsr, mTaskHandle, 0, nullptr); + const esp_timer_create_args_t timerArgs = { + .callback = &timerIsr, + .arg = (void*)&mTaskHandle, + .dispatch_method = ESP_TIMER_TASK, + .name = "link", + .skip_unhandled_events = true, + }; - timer_start(TIMER_GROUP_0, TIMER_1); + ESP_ERROR_CHECK(esp_timer_create(&timerArgs, &mTimer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(mTimer, 100)); } ~ServiceRunner() { + esp_timer_delete(mTimer); vTaskDelete(mTaskHandle); } @@ -113,6 +105,7 @@ private: TaskHandle_t mTaskHandle; + esp_timer_handle_t mTimer; std::unique_ptr<::asio::io_service> mpService; std::unique_ptr<::asio::io_service::work> mpWork; }; @@ -150,30 +143,72 @@ } template - Socket openUnicastSocket(const ::asio::ip::address_v4& addr) + Socket openUnicastSocket(const ::asio::ip::address& addr) { - auto socket = Socket{serviceRunner().service()}; + auto socket = + addr.is_v4() ? Socket{serviceRunner().service(), ::asio::ip::udp::v4()} + : Socket{serviceRunner().service(), ::asio::ip::udp::v6()}; socket.mpImpl->mSocket.set_option( ::asio::ip::multicast::enable_loopback(addr.is_loopback())); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr)); - socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0}); + if (addr.is_v4()) + { + socket.mpImpl->mSocket.set_option( + ::asio::ip::multicast::outbound_interface(addr.to_v4())); + socket.mpImpl->mSocket.bind( + ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0}); + } + else if (addr.is_v6()) + { + const auto scopeId = addr.to_v6().scope_id(); + socket.mpImpl->mSocket.set_option( + ::asio::ip::multicast::outbound_interface(static_cast(scopeId))); + socket.mpImpl->mSocket.bind( + ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0}); + } + else + { + throw(std::runtime_error("Unknown Protocol")); + } return socket; } template - Socket openMulticastSocket(const ::asio::ip::address_v4& addr) + Socket openMulticastSocket(const ::asio::ip::address& addr) { - auto socket = Socket{serviceRunner().service()}; + auto socket = + addr.is_v4() ? Socket{serviceRunner().service(), ::asio::ip::udp::v4()} + : Socket{serviceRunner().service(), ::asio::ip::udp::v6()}; + socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true)); socket.mpImpl->mSocket.set_option( ::asio::socket_base::broadcast(!addr.is_loopback())); socket.mpImpl->mSocket.set_option( ::asio::ip::multicast::enable_loopback(addr.is_loopback())); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr)); - socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"), - discovery::multicastEndpoint().port()}); - socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group( - discovery::multicastEndpoint().address().to_v4(), addr)); + + if (addr.is_v4()) + { + socket.mpImpl->mSocket.set_option( + ::asio::ip::multicast::outbound_interface(addr.to_v4())); + socket.mpImpl->mSocket.bind( + {::asio::ip::address_v4::any(), discovery::multicastEndpointV4().port()}); + socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group( + discovery::multicastEndpointV4().address().to_v4(), addr.to_v4())); + } + else if (addr.is_v6()) + { + const auto scopeId = addr.to_v6().scope_id(); + socket.mpImpl->mSocket.set_option( + ::asio::ip::multicast::outbound_interface(static_cast(scopeId))); + const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId); + socket.mpImpl->mSocket.bind( + {::asio::ip::address_v6::any(), multicastEndpoint.port()}); + socket.mpImpl->mSocket.set_option( + ::asio::ip::multicast::join_group(multicastEndpoint.address().to_v6(), scopeId)); + } + else + { + throw(std::runtime_error("Unknown Protocol")); + } return socket; } diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include #include @@ -33,9 +33,9 @@ // ESP32 implementation of ip interface address scanner struct ScanIpIfAddrs { - std::vector<::asio::ip::address> operator()() + std::vector operator()() { - std::vector<::asio::ip::address> addrs; + std::vector addrs; // Get first network interface esp_netif_t* esp_netif = esp_netif_next(NULL); while (esp_netif) diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/linux/Clock.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/linux/Clock.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/linux/Clock.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/linux/Clock.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -28,15 +28,11 @@ namespace platforms { -#ifdef linux -#undef linux -#endif - #if defined(__FreeBSD_kernel__) #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC #endif -namespace linux +namespace linux_ { template @@ -55,6 +51,6 @@ using ClockMonotonic = Clock; using ClockMonotonicRaw = Clock; -} // namespace linux +} // namespace linux_ } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/linux/ThreadFactory.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/linux/ThreadFactory.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/linux/ThreadFactory.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/linux/ThreadFactory.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -26,7 +26,7 @@ { namespace platforms { -namespace linux +namespace linux_ { struct ThreadFactory @@ -40,6 +40,6 @@ } }; -} // namespace linux +} // namespace linux_ } // namespace platforms } // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/posix/ScanIpIfAddrs.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/posix/ScanIpIfAddrs.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/posix/ScanIpIfAddrs.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/posix/ScanIpIfAddrs.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,11 +19,12 @@ #pragma once -#include -#include +#include #include #include +#include #include +#include #include namespace ableton @@ -75,34 +76,52 @@ { // Scan active network interfaces and return corresponding addresses // for all ip-based interfaces. - std::vector<::asio::ip::address> operator()() + std::vector operator()() { - std::vector<::asio::ip::address> addrs; + std::vector addrs; + std::map IpInterfaceNames; detail::GetIfAddrs getIfAddrs; - getIfAddrs.withIfAddrs([&addrs](const struct ifaddrs& interfaces) { + getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](const struct ifaddrs& interfaces) { const struct ifaddrs* interface; for (interface = &interfaces; interface; interface = interface->ifa_next) { - auto addr = reinterpret_cast(interface->ifa_addr); - if (addr && interface->ifa_flags & IFF_UP) + const auto addr = + reinterpret_cast(interface->ifa_addr); + if (addr && interface->ifa_flags & IFF_RUNNING && addr->sin_family == AF_INET) { - if (addr->sin_family == AF_INET) - { - auto bytes = reinterpret_cast(&addr->sin_addr); - addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes)); - } - else if (addr->sin_family == AF_INET6) + const auto bytes = reinterpret_cast(&addr->sin_addr); + const auto address = discovery::makeAddress(bytes); + addrs.emplace_back(address); + IpInterfaceNames.insert(std::make_pair(interface->ifa_name, address)); + } + } + }); + + getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](const struct ifaddrs& interfaces) { + const struct ifaddrs* interface; + for (interface = &interfaces; interface; interface = interface->ifa_next) + { + const auto addr = + reinterpret_cast(interface->ifa_addr); + if (IpInterfaceNames.find(interface->ifa_name) != IpInterfaceNames.end() && addr + && interface->ifa_flags & IFF_RUNNING && addr->sin_family == AF_INET6) + { + const auto addr6 = reinterpret_cast(addr); + const auto bytes = reinterpret_cast(&addr6->sin6_addr); + const auto scopeId = addr6->sin6_scope_id; + const auto address = + discovery::makeAddress(bytes, scopeId); + if (!address.is_loopback() && address.is_link_local()) { - auto addr6 = reinterpret_cast(addr); - auto bytes = reinterpret_cast(&addr6->sin6_addr); - addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes)); + addrs.emplace_back(address); } } } }); + return addrs; - } + }; }; } // namespace posix diff -Nru ableton-link-3.0.6+dfsg/include/ableton/platforms/windows/ScanIpIfAddrs.hpp ableton-link-3.1.1+dfsg/include/ableton/platforms/windows/ScanIpIfAddrs.hpp --- ableton-link-3.0.6+dfsg/include/ableton/platforms/windows/ScanIpIfAddrs.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/platforms/windows/ScanIpIfAddrs.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,10 +19,11 @@ #pragma once -#include -#include +#include #include +#include #include +#include #include #include #include @@ -99,12 +100,13 @@ { // Scan active network interfaces and return corresponding addresses // for all ip-based interfaces. - std::vector<::asio::ip::address> operator()() + std::vector operator()() { - std::vector<::asio::ip::address> addrs; + std::vector addrs; + std::map IpInterfaceNames; detail::GetIfAddrs getIfAddrs; - getIfAddrs.withIfAddrs([&addrs](const IP_ADAPTER_ADDRESSES& interfaces) { + getIfAddrs.withIfAddrs([&](const IP_ADAPTER_ADDRESSES& interfaces) { const IP_ADAPTER_ADDRESSES* networkInterface; for (networkInterface = &interfaces; networkInterface; networkInterface = networkInterface->Next) @@ -118,19 +120,45 @@ // IPv4 SOCKADDR_IN* addr4 = reinterpret_cast(address->Address.lpSockaddr); - auto bytes = reinterpret_cast(&addr4->sin_addr); - addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes)); + const auto bytes = reinterpret_cast(&addr4->sin_addr); + const auto ipv4address = + discovery::makeAddress(bytes); + addrs.emplace_back(ipv4address); + IpInterfaceNames.insert( + std::make_pair(networkInterface->AdapterName, ipv4address)); } - else if (AF_INET6 == family) + } + } + }); + + getIfAddrs.withIfAddrs([&](const IP_ADAPTER_ADDRESSES& interfaces) { + const IP_ADAPTER_ADDRESSES* networkInterface; + for (networkInterface = &interfaces; networkInterface; + networkInterface = networkInterface->Next) + { + for (IP_ADAPTER_UNICAST_ADDRESS* address = networkInterface->FirstUnicastAddress; + NULL != address; address = address->Next) + { + auto family = address->Address.lpSockaddr->sa_family; + if (AF_INET6 == family + && IpInterfaceNames.find(networkInterface->AdapterName) + != IpInterfaceNames.end()) { - SOCKADDR_IN6* addr6 = + SOCKADDR_IN6* sockAddr = reinterpret_cast(address->Address.lpSockaddr); - auto bytes = reinterpret_cast(&addr6->sin6_addr); - addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes)); + const auto scopeId = sockAddr->sin6_scope_id; + const auto bytes = reinterpret_cast(&sockAddr->sin6_addr); + const auto addr6 = + discovery::makeAddress(bytes, scopeId); + if (!addr6.is_loopback() && addr6.is_link_local()) + { + addrs.emplace_back(addr6); + } } } } }); + return addrs; } }; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/test/serial_io/Context.hpp ableton-link-3.1.1+dfsg/include/ableton/test/serial_io/Context.hpp --- ableton-link-3.0.6+dfsg/include/ableton/test/serial_io/Context.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/test/serial_io/Context.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include #include @@ -37,7 +37,7 @@ { public: Context(const SchedulerTree::TimePoint& now, - const std::vector<::asio::ip::address>& ifAddrs, + const std::vector& ifAddrs, std::shared_ptr pScheduler) : mNow(now) , mIfAddrs(ifAddrs) @@ -91,14 +91,14 @@ return mLog; } - std::vector<::asio::ip::address> scanNetworkInterfaces() + std::vector scanNetworkInterfaces() { return mIfAddrs; } private: const SchedulerTree::TimePoint& mNow; - const std::vector<::asio::ip::address>& mIfAddrs; + const std::vector& mIfAddrs; std::shared_ptr mpScheduler; Log mLog; SchedulerTree::TimerId mNextTimerId; diff -Nru ableton-link-3.0.6+dfsg/include/ableton/test/serial_io/Fixture.hpp ableton-link-3.1.1+dfsg/include/ableton/test/serial_io/Fixture.hpp --- ableton-link-3.0.6+dfsg/include/ableton/test/serial_io/Fixture.hpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/include/ableton/test/serial_io/Fixture.hpp 2024-02-01 14:19:51.000000000 +0000 @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include #include @@ -50,7 +50,7 @@ Fixture(Fixture&&) = delete; Fixture& operator=(Fixture&&) = delete; - void setNetworkInterfaces(std::vector<::asio::ip::address> ifAddrs) + void setNetworkInterfaces(std::vector ifAddrs) { mIfAddrs = std::move(ifAddrs); } @@ -84,7 +84,7 @@ private: std::shared_ptr mpScheduler; SchedulerTree::TimePoint mNow; - std::vector<::asio::ip::address> mIfAddrs; + std::vector mIfAddrs; }; } // namespace serial_io diff -Nru ableton-link-3.0.6+dfsg/src/CMakeLists.txt ableton-link-3.1.1+dfsg/src/CMakeLists.txt --- ableton-link-3.0.6+dfsg/src/CMakeLists.txt 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/CMakeLists.txt 2024-02-01 14:19:51.000000000 +0000 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) project(LinkTest) # ____ @@ -26,12 +26,14 @@ ableton/link/tst_Measurement.cpp ableton/link/tst_Median.cpp ableton/link/tst_Peers.cpp + ableton/link/tst_PeerState.cpp ableton/link/tst_Phase.cpp ableton/link/tst_PingResponder.cpp ableton/link/tst_StartStopState.cpp ableton/link/tst_Tempo.cpp ableton/link/tst_Timeline.cpp ableton/link/tst_TripleBuffer.cpp + ableton/tst_Link.cpp ) set(link_test_SOURCES diff -Nru ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_InterfaceScanner.cpp ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_InterfaceScanner.cpp --- ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_InterfaceScanner.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_InterfaceScanner.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -36,15 +36,15 @@ addrRanges.emplace_back(begin(addrs), end(addrs)); } - std::vector> addrRanges; + std::vector> addrRanges; }; } // anonymous namespace TEST_CASE("InterfaceScanner") { - const asio::ip::address addr1 = asio::ip::address::from_string("123.123.123.1"); - const asio::ip::address addr2 = asio::ip::address::from_string("123.123.123.2"); + const auto addr1 = discovery::IpAddress::from_string("123.123.123.1"); + const auto addr2 = discovery::IpAddress::from_string("123.123.123.2"); test::serial_io::Fixture io; auto callback = TestCallback{}; diff -Nru ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_PeerGateways.cpp ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_PeerGateways.cpp --- ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_PeerGateways.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_PeerGateways.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -31,7 +31,7 @@ struct Gateway { - asio::ip::address addr; + IpAddress addr; }; struct NodeState @@ -41,7 +41,7 @@ struct Factory { template - Gateway operator()(NodeState, util::Injected, const asio::ip::address& addr) + Gateway operator()(NodeState, util::Injected, const IpAddress& addr) { return {addr}; } @@ -50,7 +50,7 @@ template void expectGateways( - Gateways& gateways, test::serial_io::Fixture& io, std::vector addrs) + Gateways& gateways, test::serial_io::Fixture& io, std::vector addrs) { using namespace std; @@ -74,8 +74,8 @@ TEST_CASE("PeerGateways") { - const asio::ip::address addr1 = asio::ip::address::from_string("192.192.192.1"); - const asio::ip::address addr2 = asio::ip::address::from_string("192.192.192.2"); + const IpAddress addr1 = IpAddress::from_string("192.192.192.1"); + const IpAddress addr2 = IpAddress::from_string("192.192.192.2"); test::serial_io::Fixture io; auto pGateways = makePeerGateways( diff -Nru ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_UdpMessenger.cpp ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_UdpMessenger.cpp --- ableton-link-3.0.6+dfsg/src/ableton/discovery/tst_UdpMessenger.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/discovery/tst_UdpMessenger.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -97,8 +97,7 @@ { const TestNodeState state1 = {5, 15}; const auto state2 = TestNodeState{3, 10}; - const auto peerEndpoint = - asio::ip::udp::endpoint{asio::ip::address::from_string("123.123.234.234"), 1900}; + const auto peerEndpoint = UdpEndpoint{IpAddress::from_string("123.123.234.234"), 1900}; ::ableton::test::serial_io::Fixture io; auto iface = test::Interface{}; @@ -119,7 +118,7 @@ CHECK(state2.nodeId == result.first.ident); CHECK(1 == result.first.ttl); // Sent to the multicast endpoint - CHECK(multicastEndpoint() == sentTo); + CHECK(multicastEndpointV4() == sentTo); // And the payload should parse to equal to the original state const auto actualState = @@ -200,7 +199,7 @@ const auto result = v1::parseMessageHeader( begin(messageBuffer), end(messageBuffer)); CHECK(v1::kByeBye == result.first.messageType); - CHECK(multicastEndpoint() == sentTo); + CHECK(multicastEndpointV4() == sentTo); } SECTION("MovingMessengerDoesntSendByeBye") diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Beats.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Beats.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Beats.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Beats.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -31,14 +31,14 @@ { const auto beats = Beats{0.5}; CHECK(500000 == beats.microBeats()); - CHECK(0.5 == Approx(beats.floating())); + CHECK_THAT(0.5, Catch::Matchers::WithinAbs(beats.floating(), 1e-10)); } SECTION("ConstructFromMicros") { const auto beats = Beats{INT64_C(100000)}; CHECK(100000 == beats.microBeats()); - CHECK(0.1 == Approx(beats.floating())); + CHECK_THAT(0.1, Catch::Matchers::WithinAbs(beats.floating(), 1e-10)); } SECTION("Negation") diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Controller.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Controller.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Controller.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Controller.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -77,7 +77,7 @@ struct Socket { std::size_t send( - const uint8_t* const, const size_t numBytes, const asio::ip::udp::endpoint&) + const uint8_t* const, const size_t numBytes, const discovery::UdpEndpoint&) { return numBytes; } @@ -87,7 +87,7 @@ { } - asio::ip::udp::endpoint endpoint() const + discovery::UdpEndpoint endpoint() const { return {}; } @@ -98,18 +98,18 @@ } template - Socket openUnicastSocket(const asio::ip::address_v4&) + Socket openUnicastSocket(const discovery::IpAddress&) { return {}; } template - Socket openMulticastSocket(const asio::ip::address_v4&) + Socket openMulticastSocket(const discovery::IpAddress&) { return {}; } - std::vector scanNetworkInterfaces() + std::vector scanNetworkInterfaces() { return {}; } diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_LinearRegression.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_LinearRegression.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_LinearRegression.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_LinearRegression.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -38,8 +38,8 @@ Array data; data[0] = {0., 0.}; const auto result = linearRegression(data.begin(), data.end()); - CHECK(0 == Approx(result.first)); - CHECK(0 == Approx(result.second)); + CHECK_THAT(result.first, Catch::Matchers::WithinAbs(0, 0.00001)); + CHECK_THAT(result.second, Catch::Matchers::WithinAbs(0, 0.00001)); } SECTION("TwoPoints") @@ -49,8 +49,8 @@ data.emplace_back(666666.6, 66666.6); const auto result = linearRegression(data.begin(), data.end()); - CHECK(0.1 == Approx(result.first)); - CHECK(0.0 == Approx(result.second)); + CHECK_THAT(result.first, Catch::Matchers::WithinAbs(0.1, 0.00001)); + CHECK_THAT(result.second, Catch::Matchers::WithinAbs(0.0, 0.00001)); } SECTION("10000Points") @@ -65,8 +65,8 @@ } const auto result = linearRegression(data.begin(), data.end()); - CHECK(slope == Approx(result.first)); - CHECK(intercept == Approx(result.second)); + CHECK_THAT(slope, Catch::Matchers::WithinAbs(result.first, 1e-7)); + CHECK_THAT(intercept, Catch::Matchers::WithinAbs(result.second, 1e-7)); } SECTION("TwoPoints Float") @@ -76,8 +76,8 @@ data.emplace_back(666666.6f, 66666.6f); const auto result = linearRegression(data.begin(), data.end()); - CHECK(0.1f == Approx(result.first)); - CHECK(0.f == Approx(result.second)); + CHECK_THAT(static_cast(result.first), Catch::Matchers::WithinAbs(0.1, 0.002)); + CHECK_THAT(static_cast(result.second), Catch::Matchers::WithinAbs(0., 0.002)); } SECTION("10000Points Float") @@ -92,8 +92,10 @@ } const auto result = linearRegression(data.begin(), data.end()); - CHECK(slope == Approx(result.first)); - CHECK(intercept == Approx(result.second)); + CHECK_THAT( + slope, Catch::Matchers::WithinAbs(static_cast(result.first), 1e-3)); + CHECK_THAT( + intercept, Catch::Matchers::WithinAbs(static_cast(result.second), 1e-3)); } } diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Measurement.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Measurement.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Measurement.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Measurement.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -48,7 +48,7 @@ using Socket = discovery::test::Socket; template - Socket openUnicastSocket(const asio::ip::address_v4&) + Socket openUnicastSocket(const discovery::IpAddress&) { return Socket(mIo); } @@ -93,7 +93,7 @@ using Random = ableton::platforms::stl::Random; mState.nodeState.sessionId = NodeId::random(); mState.endpoint = - asio::ip::udp::endpoint(asio::ip::address_v4::from_string("127.0.0.1"), 9999); + discovery::UdpEndpoint(discovery::IpAddressV4::from_string("127.0.0.1"), 9999); } PeerState operator()() @@ -114,7 +114,7 @@ using Micros = std::chrono::microseconds; TFixture fixture; const auto endpoint = - asio::ip::udp::endpoint(asio::ip::address_v4::from_string("127.0.0.1"), 8888); + discovery::UdpEndpoint(discovery::IpAddressV4::from_string("127.0.0.1"), 8888); SECTION("SendPingsOnConstruction") { diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Median.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Median.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Median.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Median.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -34,19 +34,19 @@ SECTION("ArrayWithThreePoints") { auto data = std::array{{5., 0., 6.}}; - CHECK(5 == Approx(median(data.begin(), data.end()))); + CHECK_THAT(5, Catch::Matchers::WithinAbs(median(data.begin(), data.end()), 1e-10)); } SECTION("VectorWithFourPoints") { auto data = Vector{{0., 2., 1., 3., 2.}}; - CHECK(2.0 == Approx(median(data.begin(), data.end()))); + CHECK_THAT(2.0, Catch::Matchers::WithinAbs(median(data.begin(), data.end()), 1e-10)); } SECTION("VectorWithFivePoints") { auto data = Vector{{0., 1., 3., 2.}}; - CHECK(1.5 == Approx(median(data.begin(), data.end()))); + CHECK_THAT(1.5, Catch::Matchers::WithinAbs(median(data.begin(), data.end()), 1e-10)); } SECTION("VectorWith9999Points") @@ -58,7 +58,8 @@ { data.emplace_back(i * slope + intercept); } - CHECK(slope * 5000 + intercept == Approx(median(data.begin(), data.end()))); + CHECK_THAT(slope * 5000 + intercept, + Catch::Matchers::WithinAbs(median(data.begin(), data.end()), 1e-10)); } } diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_PeerState.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_PeerState.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_PeerState.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_PeerState.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,71 @@ +/* Copyright 2023, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace ableton +{ +namespace link +{ + +TEST_CASE("PeerState") +{ + auto nodeId = NodeId::random(); + const auto timeline = Timeline{Tempo{60.}, Beats{1.}, std::chrono::microseconds{100}}; + const auto startStop = + StartStopState{true, Beats{1234.}, std::chrono::microseconds{5678}}; + const auto nodeState = NodeState{nodeId, nodeId, timeline, startStop}; + + SECTION("V4RoundtripByteStreamEncoding") + { + PeerState state{nodeState, + discovery::UdpEndpoint( + {discovery::makeAddress("123.123.1.2"), 6780})}; + + const auto payload = toPayload(state); + std::vector bytes(sizeInByteStream(payload)); + const auto end = toNetworkByteStream(payload, begin(bytes)); + + const auto result = PeerState::fromPayload(nodeId, bytes.begin(), end); + CHECK(state == result); + } + + SECTION("V6RoundtripByteStreamEncoding") + { + PeerState state{ + nodeState, discovery::UdpEndpoint( + {::LINK_ASIO_NAMESPACE::ip::make_address("fe80::8080"), 6780})}; + + const auto payload = toPayload(state); + std::vector bytes(sizeInByteStream(payload)); + const auto end = toNetworkByteStream(payload, begin(bytes)); + + const auto result = PeerState::fromPayload(nodeId, bytes.begin(), end); + CHECK(state == result); + } +} + +} // namespace link +} // namespace ableton diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Peers.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Peers.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Peers.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Peers.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -104,8 +104,8 @@ Timeline{Tempo{100.}, Beats{4.}, std::chrono::microseconds{100}}, {}}, {}}; - const auto gateway1 = asio::ip::address::from_string("123.123.123.123"); - const auto gateway2 = asio::ip::address::from_string("210.210.210.210"); + const auto gateway1 = discovery::IpAddress::from_string("123.123.123.123"); + const auto gateway2 = discovery::IpAddress::from_string("210.210.210.210"); auto membership = SessionMembershipCallback{}; auto sessions = SessionTimelineCallback{}; diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_PingResponder.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_PingResponder.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_PingResponder.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_PingResponder.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -52,7 +52,7 @@ using Socket = discovery::test::Socket; template - Socket openUnicastSocket(const asio::ip::address_v4&) + Socket openUnicastSocket(const discovery::IpAddress&) { return Socket(mIo); } @@ -70,7 +70,7 @@ struct RpFixture { RpFixture() - : mAddress(asio::ip::address_v4::from_string("127.0.0.1")) + : mAddress(discovery::IpAddressV4::from_string("127.0.0.1")) , mResponder(mAddress, NodeId::random(), GhostXForm{1.0, std::chrono::microseconds{0}}, @@ -89,7 +89,7 @@ return responderSocket().sentMessages.size(); } - asio::ip::address_v4 mAddress = asio::ip::address_v4::from_string("127.0.0.1"); + discovery::IpAddressV4 mAddress = discovery::IpAddressV4::from_string("127.0.0.1"); util::Injected mIo; PingResponder mResponder; }; @@ -111,7 +111,7 @@ v1::MessageBuffer buffer; const auto msgBegin = std::begin(buffer); const auto msgEnd = v1::pingMessage(payload, msgBegin); - const auto endpoint = asio::ip::udp::endpoint(fixture.mAddress, 8888); + const auto endpoint = discovery::UdpEndpoint(fixture.mAddress, 8888); fixture.responderSocket().incomingMessage(endpoint, msgBegin, msgEnd); @@ -146,7 +146,7 @@ const auto msgBegin = std::begin(buffer); const auto msgEnd = v1::pingMessage(payload, msgBegin); - const auto endpoint = asio::ip::udp::endpoint(fixture.mAddress, 8888); + const auto endpoint = discovery::UdpEndpoint(fixture.mAddress, 8888); fixture.responderSocket().incomingMessage(endpoint, msgBegin, msgEnd); diff -Nru ableton-link-3.0.6+dfsg/src/ableton/link/tst_Tempo.cpp ableton-link-3.1.1+dfsg/src/ableton/link/tst_Tempo.cpp --- ableton-link-3.0.6+dfsg/src/ableton/link/tst_Tempo.cpp 2022-12-12 12:48:44.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/link/tst_Tempo.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -30,14 +30,14 @@ SECTION("ConstructFromBpm") { const auto tempo = Tempo{120.}; - CHECK(120. == Approx(tempo.bpm())); + CHECK_THAT(120., Catch::Matchers::WithinAbs(tempo.bpm(), 1e-10)); CHECK(std::chrono::microseconds{500000} == tempo.microsPerBeat()); } SECTION("ConstructFromMicros") { const auto tempo = Tempo{std::chrono::microseconds{500000}}; - CHECK(120. == Approx(tempo.bpm())); + CHECK_THAT(120., Catch::Matchers::WithinAbs(tempo.bpm(), 1e-10)); CHECK(std::chrono::microseconds{500000} == tempo.microsPerBeat()); } diff -Nru ableton-link-3.0.6+dfsg/src/ableton/tst_Link.cpp ableton-link-3.1.1+dfsg/src/ableton/tst_Link.cpp --- ableton-link-3.0.6+dfsg/src/ableton/tst_Link.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ableton-link-3.1.1+dfsg/src/ableton/tst_Link.cpp 2024-02-01 14:19:51.000000000 +0000 @@ -0,0 +1,51 @@ +/* Copyright 2023, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#include +#include +#include + +namespace ableton +{ + +TEST_CASE("SessionState") +{ + SECTION("ForceBeatTime") + { + using namespace std::chrono; + using namespace ableton::link; + + const auto beats = 0.; + const auto time = microseconds{23456789}; + const auto quantum = 4.; + + using SessionState = ableton::BasicLink::SessionState; + + for (auto tempo = 20.; tempo < 999.; tempo += 0.8) + { + const auto tl = Timeline{Tempo{tempo}, Beats{12345678.}, microseconds{1234567}}; + auto sessionState = SessionState({{tl, {}}, false}); + sessionState.forceBeatAtTime(beats, time, quantum); + + CHECK(beats >= sessionState.beatAtTime(time, quantum)); + } + } +} + +} // namespace ableton