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.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "networkiohandler.hpp"
|
#include "networkiohandler.hpp"
|
||||||
|
#include "../kernel.hpp"
|
||||||
#include "../../../../utils/endian.hpp"
|
#include "../../../../utils/endian.hpp"
|
||||||
|
|
||||||
namespace MarklinCAN {
|
namespace MarklinCAN {
|
||||||
@ -28,6 +29,7 @@ namespace MarklinCAN {
|
|||||||
void NetworkIOHandler::start()
|
void NetworkIOHandler::start()
|
||||||
{
|
{
|
||||||
read();
|
read();
|
||||||
|
m_kernel.started();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetworkIOHandler::send(const Message& message)
|
bool NetworkIOHandler::send(const Message& message)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the traintastic source code.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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()));
|
auto expireAfter = std::chrono::milliseconds(Random::value<int>(0, bootstrapCANInterval.count()));
|
||||||
startBootloaderCANTimer(expireAfter);
|
startBootloaderCANTimer(expireAfter);
|
||||||
startPingTimer(expireAfter + 1s);
|
startPingTimer(expireAfter + 1s);
|
||||||
|
m_kernel.started();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimulationIOHandler::startBootloaderCANTimer(std::chrono::milliseconds expireAfter)
|
void SimulationIOHandler::startBootloaderCANTimer(std::chrono::milliseconds expireAfter)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the traintastic source code.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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()
|
void SocketCANIOHandler::start()
|
||||||
{
|
{
|
||||||
read();
|
read();
|
||||||
|
m_kernel.started();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketCANIOHandler::stop()
|
void SocketCANIOHandler::stop()
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the traintastic source code.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -46,20 +46,37 @@ void TCPIOHandler::start()
|
|||||||
if(ec)
|
if(ec)
|
||||||
throw LogMessageException(LogMessage::E2003_MAKE_ADDRESS_FAILED_X, ec);
|
throw LogMessageException(LogMessage::E2003_MAKE_ADDRESS_FAILED_X, ec);
|
||||||
|
|
||||||
m_socket.connect(m_endpoint, ec);
|
m_socket.async_connect(m_endpoint,
|
||||||
if(ec)
|
[this](const boost::system::error_code& err)
|
||||||
throw LogMessageException(LogMessage::E2005_SOCKET_CONNECT_FAILED_X, ec);
|
{
|
||||||
|
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_connected = true;
|
||||||
m_socket.set_option(boost::asio::ip::tcp::no_delay(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()
|
void TCPIOHandler::stop()
|
||||||
{
|
{
|
||||||
m_socket.cancel();
|
m_socket.cancel();
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
|
m_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPIOHandler::read()
|
void TCPIOHandler::read()
|
||||||
@ -99,6 +116,11 @@ void TCPIOHandler::read()
|
|||||||
|
|
||||||
void TCPIOHandler::write()
|
void TCPIOHandler::write()
|
||||||
{
|
{
|
||||||
|
if(m_writeBufferOffset == 0 || !m_connected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_socket.async_write_some(boost::asio::buffer(m_writeBuffer.data(), m_writeBufferOffset),
|
m_socket.async_write_some(boost::asio::buffer(m_writeBuffer.data(), m_writeBufferOffset),
|
||||||
[this](const boost::system::error_code& ec, std::size_t bytesTransferred)
|
[this](const boost::system::error_code& ec, std::size_t bytesTransferred)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the traintastic source code.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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;
|
boost::asio::ip::tcp::endpoint m_endpoint;
|
||||||
std::array<std::byte, 1500> m_readBuffer;
|
std::array<std::byte, 1500> m_readBuffer;
|
||||||
size_t m_readBufferOffset;
|
size_t m_readBufferOffset;
|
||||||
|
bool m_connected = false;
|
||||||
|
|
||||||
void read() final;
|
void read() final;
|
||||||
void write() final;
|
void write() final;
|
||||||
|
|||||||
@ -159,26 +159,7 @@ void Kernel::start()
|
|||||||
Log::log(logId, e.message(), e.args());
|
Log::log(logId, e.message(), e.args());
|
||||||
error();
|
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
|
#ifndef NDEBUG
|
||||||
@ -205,6 +186,27 @@ void Kernel::stop()
|
|||||||
#endif
|
#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)
|
void Kernel::receive(const Message& message)
|
||||||
{
|
{
|
||||||
assert(isKernelThread());
|
assert(isKernelThread());
|
||||||
@ -957,7 +959,7 @@ void Kernel::changeState(State value)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case State::Started:
|
case State::Started:
|
||||||
started();
|
KernelBase::started();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -226,6 +226,12 @@ class Kernel : public ::KernelBase
|
|||||||
*/
|
*/
|
||||||
void stop();
|
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 ...
|
* \brief ...
|
||||||
*
|
*
|
||||||
|
|||||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren