marklincan: use async tcp connect the prevent "hanging", see #150
Dieser Commit ist enthalten in:
Ursprung
ea027d8d3f
Commit
0adf0584dd
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 ...
|
||||
*
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren