diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/CMakeLists.txt b/CMakeLists.txt index 6adc419..c45556b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT CMAKE_MESSAGE_CONTEXT) set(CMAKE_MESSAGE_CONTEXT_SHOW ON CACHE BOOL "Show CMake message context") endif() -project(stream VERSION 1.0.3 LANGUAGES CXX) +project(stream VERSION 1.0.4 LANGUAGES CXX) if (POLICY CMP0074) cmake_policy(SET CMP0074 NEW) @@ -67,7 +67,7 @@ target_compile_definitions(websocket INTERFACE BOOST_ALL_NO_LIB) if (NOT TARGET Boost::beast) # we are using headers only (asio and beast for websockets) - set(Boost_REQUIREDVERSION "1.71.0") + set(Boost_REQUIREDVERSION "1.90.0") set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_LIBS ON) find_package(Boost ${Boost_REQUIREDVERSION} COMPONENTS system) @@ -83,14 +83,37 @@ if (NOT TARGET Boost::beast) set(BOOST_LIBS ${Boost_LIBRARIES}) else (Boost_FOUND) - message(STATUS "Pre-installed required Boost not found. Fetching Boost 1.82.0 ...") + message(STATUS "Pre-installed required Boost not found. Fetching Boost 1.90.0 ...") get_custom_fetch_content_params(Boost FC_PARAMS) FetchContent_Declare(Boost - URL https://github.com/boostorg/boost/releases/download/boost-1.82.0/boost-1.82.0.tar.xz - URL_HASH SHA256=fd60da30be908eff945735ac7d4d9addc7f7725b1ff6fcdcaede5262d511d21e + URL https://github.com/boostorg/boost/releases/download/boost-1.90.0/boost-1.90.0-cmake.tar.xz + URL_HASH SHA256=aca59f889f0f32028ad88ba6764582b63c916ce5f77b31289ad19421a96c555f ${FC_PARAMS} ) FetchContent_MakeAvailable(Boost) + + # Set up Boost include directories for FetchContent case + # When using FetchContent, we need to manually add the Boost source directory to includes + FetchContent_GetProperties(Boost SOURCE_DIR Boost_SOURCE_DIR) + if(Boost_SOURCE_DIR) + target_include_directories(websocket INTERFACE + $ + ) + endif() + + # Exclude boost_log (has compatibility issues with Boost 1.90.0 on Windows) + if(TARGET boost_log) + set_target_properties(boost_log PROPERTIES EXCLUDE_FROM_ALL TRUE) + # Try to convert to interface library to prevent compilation + get_target_property(boost_log_type boost_log TYPE) + if(boost_log_type AND boost_log_type STREQUAL "STATIC_LIBRARY") + # Can't change type after creation, but we can try to remove sources + set_target_properties(boost_log PROPERTIES SOURCES "") + endif() + endif() + if(TARGET boost_log_setup) + set_target_properties(boost_log_setup PROPERTIES EXCLUDE_FROM_ALL TRUE) + endif() endif (Boost_FOUND) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 8fd30af..1ad3580 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -68,6 +68,24 @@ } } }, + { + "name": "msvc-22", + "hidden": true, + "generator": "Visual Studio 17 2022", + "inherits": [ + "base" + ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ "Windows" ] + } + } + }, { "name": "x64/msvc-17", "architecture": "x64", @@ -81,6 +99,20 @@ "inherits": [ "msvc-17" ] + }, + { + "name": "x64/msvc-22", + "architecture": "x64", + "inherits": [ + "msvc-22" + ] + }, + { + "name": "x86/msvc-22", + "architecture": "Win32", + "inherits": [ + "msvc-22" + ] } ] } diff --git a/include/stream/TcpClientStream.hpp b/include/stream/TcpClientStream.hpp index c962534..839ef2b 100644 --- a/include/stream/TcpClientStream.hpp +++ b/include/stream/TcpClientStream.hpp @@ -17,7 +17,7 @@ #pragma once #include -#include +#include #include #include "stream/TcpStream.hpp" @@ -58,7 +58,7 @@ namespace daq::stream { std::string m_host; std::string m_port; boost::asio::ip::tcp::resolver m_resolver; - boost::asio::deadline_timer m_connectTimer; + boost::asio::system_timer m_connectTimer; std::chrono::milliseconds m_connectTimeout; }; } diff --git a/include/stream/TcpStream.hpp b/include/stream/TcpStream.hpp index f532d49..1a4deba 100644 --- a/include/stream/TcpStream.hpp +++ b/include/stream/TcpStream.hpp @@ -17,7 +17,6 @@ #pragma once #include -#include #include #include "Stream.hpp" diff --git a/include/stream/WebsocketClientStream.hpp b/include/stream/WebsocketClientStream.hpp index 4eed99b..a758a27 100644 --- a/include/stream/WebsocketClientStream.hpp +++ b/include/stream/WebsocketClientStream.hpp @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include #include @@ -78,7 +78,7 @@ class WebsocketClientStream : public Stream std::string m_path; boost::beast::websocket::stream m_stream; boost::asio::ip::tcp::resolver m_resolver; - boost::asio::deadline_timer m_asyncOperationTimer; + boost::asio::system_timer m_asyncOperationTimer; std::chrono::milliseconds m_asyncTimeout; }; } diff --git a/src/Stream.cpp b/src/Stream.cpp index 5059591..3675f7b 100644 --- a/src/Stream.cpp +++ b/src/Stream.cpp @@ -1,10 +1,17 @@ #include "stream/Stream.hpp" +#include namespace daq::stream { void Stream::copyDataAndConsume(void* dest, size_t size) { - memcpy(dest, boost::asio::buffer_cast(m_buffer.data()), size); + auto buffers = m_buffer.data(); + // For streambuf, use boost::asio::buffer() to get a single buffer view + // This works because streambuf::data() returns a contiguous buffer sequence + auto buf = boost::asio::buffer(buffers); + // In Boost.Asio 1.90+, const_buffer has a data() member function + const void* data_ptr = buf.data(); + std::memcpy(dest, data_ptr, size); m_buffer.consume(size); } @@ -15,7 +22,11 @@ size_t Stream::size() const const uint8_t* Stream::data() const { - return boost::asio::buffer_cast(m_buffer.data()); + auto buffers = m_buffer.data(); + // Use boost::asio::buffer() to get a single buffer view from the sequence + auto buf = boost::asio::buffer(buffers); + // const_buffer has a data() member function that returns const void* + return static_cast(buf.data()); } void Stream::consume(size_t size) diff --git a/src/TcpClientStream.cpp b/src/TcpClientStream.cpp index f468b63..7bd358d 100644 --- a/src/TcpClientStream.cpp +++ b/src/TcpClientStream.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "stream/TcpClientStream.hpp" @@ -32,7 +33,7 @@ namespace daq::stream { { m_initCompletionCb(boost::system::error_code()); }; - m_ioc.dispatch(completion); + boost::asio::dispatch(m_ioc, completion); return; } // Look up the domain name. @@ -83,7 +84,7 @@ namespace daq::stream { return; } - m_connectTimer.expires_from_now(boost::posix_time::milliseconds(m_connectTimeout.count())); + m_connectTimer.expires_after(m_connectTimeout); m_connectTimer.async_wait(std::bind(&TcpClientStream::connectTimeoutCb, this, std::placeholders::_1)); // Make the connection on the IP address we got from the lookup m_socket.async_connect( diff --git a/src/WebsocketClientStream.cpp b/src/WebsocketClientStream.cpp index ddf8def..a6c964e 100644 --- a/src/WebsocketClientStream.cpp +++ b/src/WebsocketClientStream.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -37,7 +38,7 @@ void WebsocketClientStream::asyncInit(CompletionCb completionCb) { m_initCompletionCb(boost::system::error_code()); }; - m_ioc.dispatch(completion); + boost::asio::dispatch(m_ioc, completion); return; } // Look up the domain name. @@ -84,7 +85,7 @@ void WebsocketClientStream::onResolve(const boost::beast::error_code& ec, boost: return; } - m_asyncOperationTimer.expires_from_now(boost::posix_time::milliseconds(m_asyncTimeout.count())); + m_asyncOperationTimer.expires_after(m_asyncTimeout); m_asyncOperationTimer.async_wait(std::bind(&WebsocketClientStream::asyncTimeoutCb, this, std::placeholders::_1)); // Make the connection on the IP address we got from the lookup @@ -105,7 +106,7 @@ void WebsocketClientStream::onConnect(const boost::beast::error_code& ec) setOptions(); // Perform the websocket handshake - m_asyncOperationTimer.expires_from_now(boost::posix_time::milliseconds(m_asyncTimeout.count())); + m_asyncOperationTimer.expires_after(m_asyncTimeout); m_asyncOperationTimer.async_wait(std::bind(&WebsocketClientStream::asyncTimeoutCb, this, std::placeholders::_1)); boost_compatibility_utils::async_handshake(m_stream, m_host, m_path, [this](const boost::beast::error_code& err) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1d3c867..e47814d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -57,10 +57,14 @@ endif() set(STREAM_TEST_LIB stream_test_lib) add_library(${STREAM_TEST_LIB} OBJECT ${TEST_LIB_SOURCES}) -target_include_directories(${STREAM_TEST_LIB} PUBLIC ${Boost_INCLUDE_DIRS}) + +# Link to websocket target which provides Boost includes (works with both find_package and FetchContent) +target_link_libraries(${STREAM_TEST_LIB} PUBLIC daq::websocket) + target_compile_options(${STREAM_TEST_LIB} PRIVATE $<$,$,$>: -Wall -Werror ${CGOV_COMPILE_FLAGS} ${ASAN_COMPILE_FLAGS}> + $<$:/bigobj> ) target_compile_definitions(${STREAM_TEST_LIB} PRIVATE @@ -75,13 +79,11 @@ set_target_properties(${STREAM_TEST_LIB} PROPERTIES CXX_EXTENSIONS OFF ) -target_include_directories(stream_test_lib PRIVATE ../include) target_link_options(${STREAM_TEST_LIB} PRIVATE ${GCOV_LINK_FLAGS}) target_link_libraries( ${STREAM_TEST_LIB} PUBLIC ${ASAN_LIB} ${GCOV_LIB} - ${Boost_LIBRARIES} ) # Windows does not support UNIX domain sockets @@ -109,6 +111,7 @@ foreach(tgt ${targets}) target_compile_options(${tgt} PRIVATE $<$,$,$>: -Wall -Werror ${CGOV_COMPILE_FLAGS} ${ASAN_COMPILE_FLAGS}> + $<$:/bigobj> ) # requires cmake 3.13 target_link_options(${tgt} PRIVATE ${GCOV_LINK_FLAGS} )