19#include <boost/asio/connect.hpp>
20#include <boost/asio/read.hpp>
21#include <boost/asio/write.hpp>
22#include <boost/asio/post.hpp>
23#include <boost/asio/bind_executor.hpp>
31 boost::asio::ip::tcp::endpoint ep,
34 _socket(_pool.io_context()),
36 _strand(_pool.io_context()),
37 _connection_timer(_pool.io_context()),
49 _socket(_pool.io_context()),
50 _strand(_pool.io_context()),
51 _connection_timer(_pool.io_context()),
54 boost::asio::ip::address ip_address = boost::asio::ip::make_address(ip);
55 _endpoint = boost::asio::ip::tcp::endpoint(ip_address, port);
68 std::weak_ptr<Secondary> weak = shared_from_this();
69 boost::asio::post(
_strand, [weak]() {
70 auto self = weak.lock();
77 if (self->_socket.is_open()) {
82 auto handle_connect = [weak](boost::system::error_code ec) {
83 auto self = weak.lock();
86 log_error(
"secondary server: connection failed:", ec.message());
98 self->_socket.set_option(boost::asio::ip::tcp::no_delay(
true));
100 self->_connected =
true;
102 log_info(
"secondary server: connected to ", self->_endpoint);
107 self->_socket.async_connect(self->_endpoint, boost::asio::bind_executor(self->_strand, handle_connect));
111 void Secondary::Stop() {
117 _connection_timer.cancel();
118 boost::system::error_code ec;
122 void Secondary::Reconnect() {
123 std::weak_ptr<Secondary> weak = shared_from_this();
125 _connection_timer.async_wait([weak](boost::system::error_code ec) {
126 auto self = weak.lock();
134 void Secondary::AsyncRun(
size_t worker_threads) {
135 _pool.AsyncRun(worker_threads);
138 void Secondary::Write(std::shared_ptr<const carla::streaming::detail::tcp::Message> message) {
141 std::weak_ptr<Secondary> weak = shared_from_this();
142 boost::asio::post(_strand, [weak, message]() {
143 auto self = weak.lock();
145 if (!self->_socket.is_open()) {
148 self->_write_queue.push_back(message);
149 if (!self->_is_writing) {
155 void Secondary::WriteNext() {
156 if (_write_queue.empty() || !_socket.is_open()) {
157 _write_queue.clear();
163 const uint64_t generation = _write_generation;
164 std::weak_ptr<Secondary> weak = shared_from_this();
165 auto handle_sent = [weak, message, generation](
const boost::system::error_code &ec, size_t) {
166 auto self = weak.lock();
170 if (generation != self->_write_generation) {
174 log_error(
"error sending data: ", ec.message());
175 self->_write_queue.clear();
176 self->_is_writing =
false;
179 self->_write_queue.pop_front();
183 boost::asio::async_write(
185 message->GetBufferSequence(),
186 boost::asio::bind_executor(_strand, handle_sent));
193 void Secondary::Write(std::string text) {
195 Write(
Buffer(
reinterpret_cast<const unsigned char *
>(text.data()), text.size()));
198 void Secondary::Disconnect() {
200 _write_queue.clear();
203 boost::system::error_code ignored;
204 _socket.close(ignored);
207 void Secondary::ReadData() {
208 std::weak_ptr<Secondary> weak = shared_from_this();
209 boost::asio::post(_strand, [weak]() {
210 auto self = weak.lock();
216 auto message = std::make_shared<IncomingMessage>(self->_buffer_pool->Pop());
218 auto handle_read_data = [weak, message](boost::system::error_code ec,
size_t DEBUG_ONLY(bytes)) {
219 auto self = weak.lock();
226 self->GetCommander().process_command(message->pop());
232 log_error(
"secondary server: failed to read data: ", ec.message());
238 auto handle_read_header = [weak, message, handle_read_data](
239 boost::system::error_code ec,
241 auto self = weak.lock();
244 log_error(
"secondary server: the primary announced a", message->size(),
245 "byte message, larger than any valid one; disconnecting");
247 }
else if (!ec && (message->size() > 0u)) {
254 boost::asio::async_read(
257 boost::asio::bind_executor(self->_strand, handle_read_data));
260 log_error(
"secondary server: failed to read header: ", ec.message());
267 boost::asio::async_read(
269 message->size_as_buffer(),
270 boost::asio::bind_executor(self->_strand, handle_read_header));
#define DEBUG_ASSERT(predicate)
#define DEBUG_ASSERT_EQ(lhs, rhs)
#define DEBUG_ASSERT_NE(lhs, rhs)
static std::shared_ptr< BufferView > CreateFrom(Buffer &&buffer)
void Stop()
Stop the ThreadPool and join all its threads.
std::function< void(MultiGPUCommand, carla::Buffer)> callback_type
void set_secondary(std::shared_ptr< Secondary > secondary)
void set_callback(callback_type callback)
boost::asio::ip::tcp::endpoint _endpoint
Secondary(boost::asio::ip::tcp::endpoint ep, SecondaryCommands::callback_type callback)
std::shared_ptr< const carla::streaming::detail::tcp::Message > message_type
boost::asio::io_context::strand _strand
SecondaryCommands _commander
void AsyncRun(size_t worker_threads)
static time_duration seconds(size_t timeout)
void EnableKeepAlive(boost::asio::ip::tcp::socket &socket)
Lets either end notice a peer that vanished without closing the connection (a killed host,...
constexpr std::size_t kMaxMultiGpuMessageBytes
Largest message either end accepts: a frame (capped at 1 GiB by the primary) plus room for its header...
uint32_t message_size_type
This file contains definitions of common data structures used in traffic manager.
static void log_error(Args &&... args)
static void log_info(Args &&... args)