Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of UDP TX #363

Merged
merged 79 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
c709371
merge
serges147 May 15, 2024
c3a4ede
rule of 5 #verification #docs #sonar
serges147 May 15, 2024
0b62171
#verification #docs #sonar
serges147 May 15, 2024
d1b11bd
#verification #docs #sonar
serges147 Jun 3, 2024
7d39c7f
Make `IRunnable::run` as fallible. #verification #docs #sonar
serges147 Jun 6, 2024
a86f2a2
build fixes #verification #docs #sonar
serges147 Jun 6, 2024
5ce13e7
latest CETL #verification #docs #sonar
serges147 Jun 6, 2024
aea6adc
#verification #docs #sonar
serges147 Jun 6, 2024
e718503
fix sonar issue #verification #docs #sonar
serges147 Jun 6, 2024
d7a72c5
fix clang-tidy issues #verification #docs #sonar
serges147 Jun 6, 2024
ccc0e1e
build fixes #verification #docs #sonar
serges147 Jun 6, 2024
3875779
pr fixes
serges147 Jun 7, 2024
b38c6de
100% coverage for `runMediaFilters` (including transient error handler).
serges147 Jun 10, 2024
856554c
Extended `AnyErrorReport` #verification #docs #sonar
serges147 Jun 10, 2024
7d240e0
more docs for `setTransientErrorHandler`
serges147 Jun 10, 2024
792a292
Drop problematic frame of `runMediaTransmit`.
serges147 Jun 11, 2024
e2ff3c3
Cover `transport::can::TransportImpl::sendTransfer` error handling. #…
serges147 Jun 11, 2024
00c78dc
Cover `transport::can::TransportImpl::runMediaTransmit` error handling.
serges147 Jun 11, 2024
ee82f35
Cover `transport::can::TransportImpl::runMediaReceive` error handling…
serges147 Jun 11, 2024
b69232c
#verification #docs #sonar
serges147 Jun 11, 2024
ddae37b
Address 2 "cpp:S134" Sonar issues ("should not be nested too deeply")
serges147 Jun 12, 2024
5cd8c83
Address 2 "cpp:S134" Sonar issues ("should not be nested too deeply"…
serges147 Jun 12, 2024
04110ac
Merge branch 'sshirokov/344_fallible_run2' of https://github.com/Open…
serges147 Jun 12, 2024
a3341c3
Use `std::exchange` at `CanardMemory` move constructor. #verification…
serges147 Jun 12, 2024
13cd2ed
First draft of UDP (dummy) entities. #verification #docs #sonar
serges147 Jun 12, 2024
1691c2c
minor fixes #verification #docs #sonar
serges147 Jun 13, 2024
96c43ab
Merge branch 'main' into sshirokov/344_fallible_run2
serges147 Jun 13, 2024
19dc98d
Merge branch 'sshirokov/344_fallible_run2' into sshirokov/udp
serges147 Jun 13, 2024
ddbd62d
minor Sonar fixes #verification #docs #sonar
serges147 Jun 13, 2024
b9161f4
minor fixes #verification #docs #sonar
serges147 Jun 13, 2024
e53f671
minor fixes #verification #docs #sonar
serges147 Jun 13, 2024
2e21ac0
minor Sonar fixes #verification #docs #sonar
serges147 Jun 13, 2024
8c74523
try to fix build #verification #docs #sonar
serges147 Jun 13, 2024
3c14506
try to fix build #verification #docs #sonar
serges147 Jun 13, 2024
c0a174b
add stubs of UDP sessions
serges147 Jun 13, 2024
73883ae
move `TransientErrorHandler` under `can::` #verification #docs #sonar
serges147 Jun 13, 2024
d5cf457
build fixes
serges147 Jun 13, 2024
aeb8929
Migrate from `Operation` enum to nested `TransientErrorReport::Xxx` r…
serges147 Jun 13, 2024
d311135
Removed RTTI registrations for `IMedia*` & `CanardInstance*` types.
serges147 Jun 13, 2024
c7b12a3
Merge branch 'sshirokov/344_fallible_run2' into sshirokov/udp
serges147 Jun 13, 2024
bf62955
break `udp/transport` → to 2 files
serges147 Jun 13, 2024
4e60e3f
Enable `makeXxxSession` methods. #verification #docs #sonar
serges147 Jun 14, 2024
cdd2f1a
build fix and more coverage #verification #docs #sonar
serges147 Jun 14, 2024
14effd6
#verification #docs #sonar
serges147 Jun 14, 2024
7e359ee
implementation of msg tx session `send` #verification #docs #sonar
serges147 Jun 14, 2024
38145d7
implemented flushing of udpard TX queues #verification #docs #sonar
serges147 Jun 17, 2024
a4f3937
fix some sonar issues #verification #docs #sonar
serges147 Jun 17, 2024
fe9d867
Implemented SVC sessions `send` method #verification #docs #sonar
serges147 Jun 17, 2024
82f60d0
Use `std::numeric_limits<TransferId>::max()` as UDP transfer id modul…
serges147 Jun 17, 2024
78b2cc2
pr review fix
serges147 Jun 17, 2024
f6ab586
Merge branch 'sshirokov/344_fallible_run2' into sshirokov/udp
serges147 Jun 17, 2024
96aa128
added `setTransientErrorHandler` @ UDP #verification #docs #sonar
serges147 Jun 17, 2024
7c78a81
Added `ITxSocket` & `IRxSocket` interfaces and their mocks. #verifica…
serges147 Jun 17, 2024
e257481
#verification #docs #sonar
serges147 Jun 17, 2024
ac08c6e
Make media TX sockets on demand #verification #docs #sonar
serges147 Jun 18, 2024
eafbcc4
fix build issue #verification #docs #sonar
serges147 Jun 18, 2024
f62818f
fix build issue #verification #docs #sonar
serges147 Jun 18, 2024
410bdda
fix build issue #verification #docs #sonar
serges147 Jun 18, 2024
3314134
refactor `switch` → `visit` ; fix build issue #verification #docs #sonar
serges147 Jun 18, 2024
9df19d8
Use UDPARD_MTU_DEFAULT
serges147 Jun 18, 2024
7434547
even more corrections #verification #docs #sonar
serges147 Jun 19, 2024
15cc8ca
latest CETL #verification #docs #sonar
serges147 Jun 19, 2024
855bc97
Implemented UDP `runMediaTransmit` #verification #docs #sonar
serges147 Jun 20, 2024
f7ef21e
Added `deadline` at UDP `ITxSocket::send` method #verification #docs …
serges147 Jun 20, 2024
08cc024
More UDP transport tests #verification #docs #sonar
serges147 Jun 20, 2024
5d5f3df
More UDP TX sessions tests #verification #docs #sonar
serges147 Jun 20, 2024
298a1dc
Merge branch 'main' into sshirokov/udp #verification #docs #sonar
serges147 Jun 21, 2024
6f589f1
fix some sonar issues #sonar
serges147 Jun 21, 2024
b93d529
fix some sonar issues #sonar
serges147 Jun 21, 2024
d86c53c
fix some sonar issues #sonar
serges147 Jun 21, 2024
1b49385
fix some sonar issues #sonar
serges147 Jun 21, 2024
a69d988
fix some sonar issues #sonar
serges147 Jun 21, 2024
ebed645
fix some sonar issues #sonar
serges147 Jun 21, 2024
3c79838
fix some sonar issues #sonar
serges147 Jun 21, 2024
591cb10
fix some sonar issues #sonar
serges147 Jun 21, 2024
bbb03e7
fix some sonar issues #sonar
serges147 Jun 21, 2024
74c1381
fix some sonar issues #verification #docs #sonar
serges147 Jun 21, 2024
723eec0
minor sonar fix
serges147 Jun 21, 2024
cfce6c9
Take advantage of `next_in_transfer` field during TX.
serges147 Jun 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/modules/Findcetl.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

include(FetchContent)
set(cetl_GIT_REPOSITORY "https://github.com/OpenCyphal/cetl.git")
set(cetl_GIT_TAG "5aa0a5b62427547b63cbbf966bcc4cde2abe396e")
set(cetl_GIT_TAG "a1ba92512924e4851ce95dd68b4525a6f9d4fc75")

FetchContent_Declare(
cetl
Expand Down
1 change: 0 additions & 1 deletion include/libcyphal/runnable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#ifndef LIBCYPHAL_RUNNABLE_HPP_INCLUDED
#define LIBCYPHAL_RUNNABLE_HPP_INCLUDED

#include "transport/errors.hpp"
#include "types.hpp"

#include <cetl/unbounded_variant.hpp>
Expand Down
2 changes: 1 addition & 1 deletion include/libcyphal/transport/can/can_transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#ifndef LIBCYPHAL_TRANSPORT_CAN_TRANSPORT_HPP_INCLUDED
#define LIBCYPHAL_TRANSPORT_CAN_TRANSPORT_HPP_INCLUDED

#include "libcyphal/transport/can/media.hpp"
#include "libcyphal/transport/errors.hpp"
#include "libcyphal/transport/transport.hpp"
#include "media.hpp"
thirtytwobits marked this conversation as resolved.
Show resolved Hide resolved

#include <canard.h>
#include <cetl/pf17/cetlpf.hpp>
Expand Down
242 changes: 128 additions & 114 deletions include/libcyphal/transport/can/can_transport_impl.hpp

Large diffs are not rendered by default.

114 changes: 81 additions & 33 deletions include/libcyphal/transport/can/delegate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <utility>

namespace libcyphal
{
Expand Down Expand Up @@ -73,7 +74,8 @@ class TransportDelegate
{
if (buffer_ != nullptr)
{
delegate_.freeCanardMemory(buffer_);
// No Sonar `cpp:S5356` b/c we integrate here with C libcanard memory management.
delegate_.freeCanardMemory(buffer_); // NOSONAR cpp:S5356
}
}

Expand Down Expand Up @@ -101,8 +103,9 @@ class TransportDelegate

const std::size_t bytes_to_copy = std::min(length_bytes, payload_size_ - offset_bytes);
// Next nolint is unavoidable: we need offset from the beginning of the buffer.
// No Sonar `cpp:S5356` b/c we integrate here with libcanard raw C buffers.
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
(void) std::memmove(destination, buffer_ + offset_bytes, bytes_to_copy);
(void) std::memmove(destination, buffer_ + offset_bytes, bytes_to_copy); // NOSONAR cpp:S5356
return bytes_to_copy;
}

Expand All @@ -127,7 +130,8 @@ class TransportDelegate
/// Recursion goes first to the left child, then to the current node, and finally to the right child.
/// B/c AVL tree is balanced, the total complexity is `O(n)` and call stack depth should not be deeper than
/// ~O(log(N)) (`ceil(1.44 * log2(N + 2) - 0.328)` to be precise, or 19 in case of 8192 ports),
/// where `N` is the total number of tree nodes. Hence, the `NOLINTNEXTLINE(misc-no-recursion)` exception.
/// where `N` is the total number of tree nodes. Hence, the `NOLINTNEXTLINE(misc-no-recursion)`
/// and `NOSONAR cpp:S925` exceptions.
///
/// @tparam Visitor Type of the visitor callable.
/// @param node (sub-)root node of the AVL tree. Could be `nullptr`.
Expand All @@ -146,45 +150,50 @@ class TransportDelegate
// Initial `1` is for the current node.
std::size_t count = 1;

count += visitCounting(node->lr[0], visitor);
count += visitCounting(node->lr[0], visitor); // NOSONAR cpp:S925

// Next nolint & NOSONAR are unavoidable: this is integration with low-level C code of Canard AVL trees.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
visitor(*reinterpret_cast<Node*>(node)); // NOSONAR cpp:S3630

count += visitCounting(node->lr[1], visitor);
count += visitCounting(node->lr[1], visitor); // NOSONAR cpp:S925

return count;
}

}; // CanardConcreteTree

enum class FiltersUpdateCondition : std::uint8_t
struct FiltersUpdate
{
SubjectPortAdded,
SubjectPortRemoved,
ServicePortAdded,
ServicePortRemoved
};
struct SubjectPort
{
bool is_added;
};
struct ServicePort
{
bool is_added;
};

explicit TransportDelegate(cetl::pmr::memory_resource& memory)
: memory_{memory}
, canard_instance_{::canardInit(allocateMemoryForCanard, freeCanardMemory)}
{
canard_instance().user_reference = this;
}
using Variant = cetl::variant<SubjectPort, ServicePort>;

}; // FiltersUpdate

TransportDelegate(const TransportDelegate&) = delete;
TransportDelegate(TransportDelegate&&) noexcept = delete;
TransportDelegate& operator=(const TransportDelegate&) = delete;
TransportDelegate& operator=(TransportDelegate&&) noexcept = delete;

CETL_NODISCARD CanardInstance& canard_instance() noexcept
CETL_NODISCARD NodeId node_id() const noexcept
{
return canard_instance_;
return canard_instance_.node_id;
}

CETL_NODISCARD const CanardInstance& canard_instance() const noexcept
CETL_NODISCARD CanardNodeID& canard_node_id() noexcept
{
return canard_instance_.node_id;
}

CETL_NODISCARD CanardInstance& canard_instance() noexcept
{
return canard_instance_;
}
Expand Down Expand Up @@ -213,21 +222,46 @@ class TransportDelegate

/// @brief Releases memory allocated for canard (by previous `allocateMemoryForCanard` call).
///
/// NOSONAR cpp:S5008 b/s it is unavoidable: this is integration with low-level C code of Canard memory management.
/// No Sonar `cpp:S5008` and `cpp:S5356` b/c they are unavoidable -
/// this is integration with low-level C code of Canard memory management.
///
void freeCanardMemory(void* const pointer) // NOSONAR cpp:S5008
void freeCanardMemory(void* const pointer) const // NOSONAR cpp:S5008
{
if (pointer == nullptr)
{
return;
}

auto* memory_header = static_cast<CanardMemoryHeader*>(pointer);
auto* memory_header = static_cast<CanardMemoryHeader*>(pointer); // NOSONAR cpp:S5356
// Next nolint is unavoidable: this is integration with C code of Canard memory management.
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
--memory_header;

memory_.deallocate(memory_header, memory_header->size);
memory_.deallocate(memory_header, memory_header->size); // NOSONAR cpp:S5356
}

/// Pops and frees Canard TX queue item(s).
///
/// @param tx_queue The TX queue from which the item should be popped.
/// @param tx_item The TX queue item to be popped and freed.
/// @param whole_transfer If `true` then whole transfer should be released from the queue.
///
void popAndFreeCanardTxQueueItem(CanardTxQueue* const tx_queue,
const CanardTxQueueItem* tx_item,
const bool whole_transfer) const
{
while (CanardTxQueueItem* const mut_tx_item = ::canardTxPop(tx_queue, tx_item))
{
tx_item = tx_item->next_in_transfer;

// No Sonar `cpp:S5356` b/c we need to free tx item allocated by libcanard as a raw memory.
freeCanardMemory(mut_tx_item); // NOSONAR cpp:S5356

if (!whole_transfer)
{
break;
}
}
}

/// @brief Sends transfer to each media canard TX queue of the transport.
Expand All @@ -242,12 +276,20 @@ class TransportDelegate
///
/// Actual update will be done on next `run` of transport.
///
/// @param condition Describes condition in which the RX ports change has happened. Allows to distinguish
/// between subject and service ports, and between adding and removing a port.
/// @param update_var Describes variant of which the RX ports update has happened.
/// Allows to distinguish between subject and service ports.
///
virtual void triggerUpdateOfFilters(const FiltersUpdateCondition condition) noexcept = 0;
virtual void triggerUpdateOfFilters(const FiltersUpdate::Variant& update_var) = 0;

protected:
explicit TransportDelegate(cetl::pmr::memory_resource& memory)
: memory_{memory}
, canard_instance_{::canardInit(allocateMemoryForCanard, freeCanardMemory)}
{
// No Sonar `cpp:S5356` b/c we integrate here with C libcanard API.
canard_instance().user_reference = this; // NOSONAR cpp:S5356
}

~TransportDelegate() = default;

private:
Expand All @@ -270,7 +312,9 @@ class TransportDelegate
CETL_DEBUG_ASSERT(ins != nullptr, "Expected canard instance.");
CETL_DEBUG_ASSERT(ins->user_reference != nullptr, "Expected `this` transport as user reference.");

return *static_cast<TransportDelegate*>(ins->user_reference);
// No Sonar `cpp:S5357` b/c the raw `user_reference` is part of libcanard api,
// and it was set by us at this delegate constructor (see `TransportDelegate` ctor).
return *static_cast<TransportDelegate*>(ins->user_reference); // NOSONAR cpp:S5357
}

/// @brief Allocates memory for canard instance.
Expand All @@ -285,8 +329,11 @@ class TransportDelegate
{
TransportDelegate& self = getSelfFrom(ins);

const std::size_t memory_size = sizeof(CanardMemoryHeader) + amount;
auto* memory_header = static_cast<CanardMemoryHeader*>(self.memory_.allocate(memory_size));
const std::size_t memory_size = sizeof(CanardMemoryHeader) + amount;

// No Sonar `cpp:S5356` and `cpp:S5357` b/c we integrate here with C libcanard memory management.
auto* memory_header =
static_cast<CanardMemoryHeader*>(self.memory_.allocate(memory_size)); // NOSONAR cpp:S5356 cpp:S5357
if (memory_header == nullptr)
{
return nullptr;
Expand All @@ -296,9 +343,10 @@ class TransportDelegate
// The size is used in `canardMemoryFree` to deallocate the memory.
//
memory_header->size = memory_size;
// Next nolint is unavoidable: this is integration with C code of Canard memory management.
// Next nolint and no Sonar `cpp:S5356` are unavoidable -
// this is integration with C code of Canard memory management.
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
return ++memory_header;
return ++memory_header; // NOSONAR cpp:S5356
}

/// @brief Releases memory allocated for canard instance (by previous `allocateMemoryForCanard` call).
Expand All @@ -309,7 +357,7 @@ class TransportDelegate
static void freeCanardMemory(CanardInstance* ins, // NOSONAR cpp:S995
void* pointer) // NOSONAR cpp:S5008
{
TransportDelegate& self = getSelfFrom(ins);
const TransportDelegate& self = getSelfFrom(ins);
self.freeCanardMemory(pointer);
}

Expand Down
3 changes: 3 additions & 0 deletions include/libcyphal/transport/can/media.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class IMedia

/// @brief Schedules the frame for transmission asynchronously and return immediately.
///
/// @param deadline The deadline for the push operation. Media implementation should drop the payload
/// if the deadline is exceeded (aka `now > deadline`).
/// @param can_id The destination CAN ID of the frame.
/// @return `true` if the frame is accepted or already timed out;
/// `false` to try again later (f.e. b/c output TX queue is currently full).
/// If any media error occurred, the frame will be dropped by transport.
Expand Down
30 changes: 13 additions & 17 deletions include/libcyphal/transport/can/msg_rx_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,11 @@ namespace detail
///
class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSession // NOSONAR cpp:S4963
{
/// @brief Defines specification for making interface unique ptr.
/// @brief Defines private specification for making interface unique ptr.
///
struct Spec
struct Spec : libcyphal::detail::UniquePtrSpec<IMessageRxSession, MessageRxSession>
{
using Interface = IMessageRxSession;
using Concrete = MessageRxSession;

// In use to disable public construction.
// `explicit` here is in use to disable public construction of derived private `Spec` structs.
// See https://seanmiddleditch.github.io/enabling-make-unique-with-private-constructors/
explicit Spec() = default;
};
Expand All @@ -73,7 +70,7 @@ class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSess
return session;
}

MessageRxSession(Spec, TransportDelegate& delegate, const MessageRxParams& params)
MessageRxSession(const Spec, TransportDelegate& delegate, const MessageRxParams& params)
: delegate_{delegate}
, params_{params}
, subscription_{}
Expand All @@ -88,9 +85,10 @@ class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSess
CETL_DEBUG_ASSERT(result >= 0, "There is no way currently to get an error here.");
CETL_DEBUG_ASSERT(result > 0, "New subscription supposed to be made.");

subscription_.user_reference = static_cast<IRxSessionDelegate*>(this);
// No Sonar `cpp:S5356` b/c we integrate here with C libcanard API.
subscription_.user_reference = static_cast<IRxSessionDelegate*>(this); // NOSONAR cpp:S5356

delegate_.triggerUpdateOfFilters(TransportDelegate::FiltersUpdateCondition::SubjectPortAdded);
delegate_.triggerUpdateOfFilters(TransportDelegate::FiltersUpdate::SubjectPort{true});
}

MessageRxSession(const MessageRxSession&) = delete;
Expand All @@ -106,7 +104,7 @@ class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSess
CETL_DEBUG_ASSERT(result >= 0, "There is no way currently to get an error here.");
CETL_DEBUG_ASSERT(result > 0, "Subscription supposed to be made at constructor.");

delegate_.triggerUpdateOfFilters(TransportDelegate::FiltersUpdateCondition::SubjectPortRemoved);
delegate_.triggerUpdateOfFilters(TransportDelegate::FiltersUpdate::SubjectPort{false});
}

private:
Expand All @@ -119,9 +117,7 @@ class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSess

CETL_NODISCARD cetl::optional<MessageRxTransfer> receive() override
{
cetl::optional<MessageRxTransfer> result{};
result.swap(last_rx_transfer_);
return result;
return std::exchange(last_rx_transfer_, cetl::nullopt);
}

// MARK: IRxSession
Expand Down Expand Up @@ -156,11 +152,11 @@ class MessageRxSession final : private IRxSessionDelegate, public IMessageRxSess
? cetl::nullopt
: cetl::make_optional<NodeId>(transfer.metadata.remote_node_id);

const MessageTransferMetadata meta{transfer_id, timestamp, priority, publisher_node_id};
TransportDelegate::CanardMemory canard_memory{delegate_,
static_cast<cetl::byte*>(transfer.payload),
transfer.payload_size};
// No Sonar `cpp:S5356` and `cpp:S5357` b/c we need to pass raw data from C libcanard api.
auto* const buffer = static_cast<cetl::byte*>(transfer.payload); // NOSONAR cpp:S5356 cpp:S5357
TransportDelegate::CanardMemory canard_memory{delegate_, buffer, transfer.payload_size};

const MessageTransferMetadata meta{transfer_id, timestamp, priority, publisher_node_id};
(void) last_rx_transfer_.emplace(MessageRxTransfer{meta, ScatteredBuffer{std::move(canard_memory)}});
}

Expand Down
11 changes: 4 additions & 7 deletions include/libcyphal/transport/can/msg_tx_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,11 @@ namespace detail

class MessageTxSession final : public IMessageTxSession
{
/// @brief Defines specification for making interface unique ptr.
/// @brief Defines private specification for making interface unique ptr.
///
struct Spec
struct Spec : libcyphal::detail::UniquePtrSpec<IMessageTxSession, MessageTxSession>
{
using Interface = IMessageTxSession;
using Concrete = MessageTxSession;

// In use to disable public construction.
// `explicit` here is in use to disable public construction of derived private `Spec` structs.
// See https://seanmiddleditch.github.io/enabling-make-unique-with-private-constructors/
explicit Spec() = default;
};
Expand All @@ -63,7 +60,7 @@ class MessageTxSession final : public IMessageTxSession
return session;
}

MessageTxSession(Spec, TransportDelegate& delegate, const MessageTxParams& params)
MessageTxSession(const Spec, TransportDelegate& delegate, const MessageTxParams& params)
: delegate_{delegate}
, params_{params}
, send_timeout_{std::chrono::seconds{1}}
Expand Down
Loading
Loading