marklincan: use async tcp connect the prevent "hanging", see #150

Dieser Commit ist enthalten in:
Reinder Feenstra 2024-06-25 22:46:54 +02:00
Ursprung ea027d8d3f
Commit 0adf0584dd
7 geänderte Dateien mit 66 neuen und 31 gelöschten Zeilen

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
* Copyright (C) 2023-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,6 +21,7 @@
*/
#include "networkiohandler.hpp"
#include "../kernel.hpp"
#include "../../../../utils/endian.hpp"
namespace MarklinCAN {
@ -28,6 +29,7 @@ namespace MarklinCAN {
void NetworkIOHandler::start()
{
read();
m_kernel.started();
}
bool NetworkIOHandler::send(const Message& message)

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
* Copyright (C) 2023-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -42,6 +42,7 @@ void SimulationIOHandler::start()
auto expireAfter = std::chrono::milliseconds(Random::value<int>(0, bootstrapCANInterval.count()));
startBootloaderCANTimer(expireAfter);
startPingTimer(expireAfter + 1s);
m_kernel.started();
}
void SimulationIOHandler::startBootloaderCANTimer(std::chrono::milliseconds expireAfter)

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
* Copyright (C) 2023-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -67,6 +67,7 @@ SocketCANIOHandler::SocketCANIOHandler(Kernel& kernel, const std::string& interf
void SocketCANIOHandler::start()
{
read();
m_kernel.started();
}
void SocketCANIOHandler::stop()

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
* Copyright (C) 2023-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -46,20 +46,37 @@ void TCPIOHandler::start()
if(ec)
throw LogMessageException(LogMessage::E2003_MAKE_ADDRESS_FAILED_X, ec);
m_socket.connect(m_endpoint, ec);
if(ec)
throw LogMessageException(LogMessage::E2005_SOCKET_CONNECT_FAILED_X, ec);
m_socket.async_connect(m_endpoint,
[this](const boost::system::error_code& err)
{
if(!err)
{
m_socket.set_option(boost::asio::socket_base::linger(true, 0));
m_socket.set_option(boost::asio::ip::tcp::no_delay(true));
m_socket.set_option(boost::asio::socket_base::linger(true, 0));
m_socket.set_option(boost::asio::ip::tcp::no_delay(true));
m_connected = true;
NetworkIOHandler::start();
write();
NetworkIOHandler::start();
}
else if(err != boost::asio::error::operation_aborted)
{
EventLoop::call(
[this, err]()
{
Log::log(m_kernel.logId, LogMessage::E2005_SOCKET_CONNECT_FAILED_X, err);
m_kernel.error();
});
}
});
}
void TCPIOHandler::stop()
{
m_socket.cancel();
m_socket.close();
m_connected = false;
}
void TCPIOHandler::read()
@ -99,6 +116,11 @@ void TCPIOHandler::read()
void TCPIOHandler::write()
{
if(m_writeBufferOffset == 0 || !m_connected)
{
return;
}
m_socket.async_write_some(boost::asio::buffer(m_writeBuffer.data(), m_writeBufferOffset),
[this](const boost::system::error_code& ec, std::size_t bytesTransferred)
{

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
* Copyright (C) 2023-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -38,6 +38,7 @@ class TCPIOHandler final : public NetworkIOHandler
boost::asio::ip::tcp::endpoint m_endpoint;
std::array<std::byte, 1500> m_readBuffer;
size_t m_readBufferOffset;
bool m_connected = false;
void read() final;
void write() final;

Datei anzeigen

@ -159,26 +159,7 @@ void Kernel::start()
Log::log(logId, e.message(), e.args());
error();
});
return;
}
// add Traintastic to the node list
{
Node node;
node.uid = m_config.nodeUID;
node.deviceName = nodeDeviceName;
node.articleNumber = nodeArticleNumber;
node.serialNumber = m_config.nodeSerialNumber;
node.softwareVersionMajor = TRAINTASTIC_VERSION_MAJOR;
node.softwareVersionMinor = TRAINTASTIC_VERSION_MINOR;
node.deviceId = DeviceId::Traintastic;
nodeChanged(node);
m_nodes.emplace(m_config.nodeUID, node);
}
nextState();
});
#ifndef NDEBUG
@ -205,6 +186,27 @@ void Kernel::stop()
#endif
}
void Kernel::started()
{
// add Traintastic to the node list
{
Node node;
node.uid = m_config.nodeUID;
node.deviceName = nodeDeviceName;
node.articleNumber = nodeArticleNumber;
node.serialNumber = m_config.nodeSerialNumber;
node.softwareVersionMajor = TRAINTASTIC_VERSION_MAJOR;
node.softwareVersionMinor = TRAINTASTIC_VERSION_MINOR;
node.deviceId = DeviceId::Traintastic;
nodeChanged(node);
m_nodes.emplace(m_config.nodeUID, node);
}
nextState();
}
void Kernel::receive(const Message& message)
{
assert(isKernelThread());
@ -957,7 +959,7 @@ void Kernel::changeState(State value)
break;
case State::Started:
started();
KernelBase::started();
break;
}
}

Datei anzeigen

@ -226,6 +226,12 @@ class Kernel : public ::KernelBase
*/
void stop();
/**
* \brief Notify kernel the IO handler is started.
* \note This function must run in the kernel's IO context
*/
void started() final;
/**
* \brief ...
*