Commit 12ee9dc5 authored by Pavel Vainerman's avatar Pavel Vainerman Committed by Pavel Vainerman

[modbus slave]: supported socket reopen timeout

parent a8ff6725
......@@ -248,6 +248,13 @@ namespace uniset
vmonit(sessTimeout);
tmpval = conf->getArgInt("--" + prefix + "-socket-timeout", it.getProp("socketTimeout"));
if( tmpval > 0 )
sockTimeout = tmpval;
vmonit(sockTimeout);
tmpval = conf->getArgInt("--" + prefix + "-session-maxnum", it.getProp("sessMaxNum"));
if( tmpval > 0 )
......@@ -642,6 +649,8 @@ namespace uniset
i.second.ptTimeout.reset();
tcpserver->setMaxSessions( sessMaxNum );
tcpserver->setSessionTimeout(sessTimeout);
tcpserver->setSocketTimeout(sockTimeout);
if( vaddr.empty() )
{
......
......@@ -596,6 +596,7 @@ namespace uniset
// TCPServer section..
void initTCPClients( UniXML::iterator confnode );
timeout_t sockTimeout = { UniSetTimer::WaitUpTime }; /*!< таймаут на переоткрытие сокета (если нет сессий) */
timeout_t sessTimeout = { 2000 }; /*!< таймаут на сессию */
timeout_t updateStatTime = { 4000 };
ModbusTCPServer::Sessions sess; /*!< список открытых сессий */
......
......@@ -92,6 +92,12 @@ namespace uniset
void setTimer( timeout_t msec );
timeout_t getTimer() const noexcept;
// Таймаут для переоткрытия сокета.
// Если в течение msec миллисекунд нет действующих соединений
// сокет переоткрывается
void setSocketTimeout( timeout_t msec );
timeout_t getSocketTimeout() const noexcept;
protected:
// ожидание (при этом время отдаётся eventloop-у)
......@@ -105,6 +111,8 @@ namespace uniset
virtual void ioAccept(ev::io& watcher, int revents);
void onTimer( ev::timer& t, int revents );
void onSocketTimeout( ev::timer& t, int revents );
void onSocketResetTimeout( ev::async& watcher, int revents ) noexcept;
void sessionFinished( const ModbusTCPSession* s );
......@@ -145,6 +153,11 @@ namespace uniset
ev::timer ioTimer;
std::shared_ptr<UTCPSocket> sock;
ev::timer sockTimeout;
timeout_t socketTimeout_msec = { UniSetTimer::WaitUpTime };
double tmSockTimeout = { 0.0 };
ev::async asyncResetSockTimeout;
std::unordered_set<ModbusRTU::ModbusAddr> vmbaddr;
TimerSignal m_timer_signal;
......@@ -154,6 +167,8 @@ namespace uniset
PassiveTimer ptWait;
private:
void createSocket();
// транслирование сигналов от Sessions..
void postReceiveEvent( ModbusRTU::mbErrCode res );
ModbusRTU::mbErrCode preReceiveEvent( const std::unordered_set<ModbusRTU::ModbusAddr> vaddr, timeout_t tout );
......
......@@ -46,6 +46,8 @@ namespace uniset
io.set<ModbusTCPServer, &ModbusTCPServer::ioAccept>(this);
ioTimer.set<ModbusTCPServer, &ModbusTCPServer::onTimer>(this);
sockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketTimeout>(this);
asyncResetSockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketResetTimeout>(this);
}
// -------------------------------------------------------------------------
......@@ -108,36 +110,50 @@ namespace uniset
return evIsActive() && sock;
}
// -------------------------------------------------------------------------
void ModbusTCPServer::evprepare()
void ModbusTCPServer::createSocket()
{
try
{
sock = make_shared<UTCPSocket>(iaddr, port);
auto tmpSock = make_shared<UTCPSocket>(iaddr, port);
if( sock )
sock.reset();
sock = tmpSock;
}
catch( const Poco::Net::NetException& ex )
{
ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl;
throw uniset::SystemError(err.str());
}
catch( const std::exception& ex )
{
ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl;
throw uniset::SystemError(err.str());
}
sock->setBlocking(false);
}
// -------------------------------------------------------------------------
void ModbusTCPServer::evprepare()
{
createSocket();
io.set(loop);
io.start(sock->getSocket(), ev::READ);
ioTimer.set(loop);
asyncResetSockTimeout.set(loop);
asyncResetSockTimeout.start();
ioTimer.set(loop);
if( tmTime_msec != UniSetTimer::WaitUpTime )
ioTimer.start(0, tmTime);
sockTimeout.set(loop);
if( socketTimeout_msec > 0 && socketTimeout_msec != UniSetTimer::WaitUpTime )
sockTimeout.start(0, tmSockTimeout);
}
// -------------------------------------------------------------------------
void ModbusTCPServer::terminate()
......@@ -155,6 +171,8 @@ namespace uniset
ioTimer.stop();
io.stop();
sockTimeout.stop();
asyncResetSockTimeout.stop();
auto lst(slist);
......@@ -183,6 +201,7 @@ namespace uniset
{
slist.erase(i);
sessCount--;
asyncResetSockTimeout.send();
return;
}
}
......@@ -238,7 +257,29 @@ namespace uniset
// -------------------------------------------------------------------------
timeout_t ModbusTCPServer::getTimer() const noexcept
{
return tmTime;
return tmTime_msec;
}
// -------------------------------------------------------------------------
void ModbusTCPServer::setSocketTimeout( timeout_t msec )
{
socketTimeout_msec = msec;
if( msec == UniSetTimer::WaitUpTime || msec == 0 )
{
socketTimeout_msec = 0;
if( sockTimeout.is_active() )
sockTimeout.stop();
}
else
{
tmSockTimeout = (double)msec / 1000.;
if( sockTimeout.is_active() )
sockTimeout.start( 0, tmSockTimeout );
}
}
// ------------------------------------------------------------------------
timeout_t ModbusTCPServer::getSocketTimeout() const noexcept
{
return socketTimeout_msec;
}
// -------------------------------------------------------------------------
void ModbusTCPServer::iowait( timeout_t msec )
......@@ -286,6 +327,9 @@ namespace uniset
connCount++;
if( sockTimeout.is_active() )
sockTimeout.again();
auto s = make_shared<ModbusTCPSession>(ss, vmbaddr, sessTimeout);
s->connectReadCoil( sigc::mem_fun(this, &ModbusTCPServer::readCoilStatus) );
s->connectReadInputStatus( sigc::mem_fun(this, &ModbusTCPServer::readInputStatus) );
......@@ -331,26 +375,83 @@ namespace uniset
// -------------------------------------------------------------------------
void ModbusTCPServer::onTimer( ev::timer& t, int revents )
{
if (EV_ERROR & revents)
{
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::ioTimer): invalid event" << endl;
if (EV_ERROR & revents)
{
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::ioTimer): invalid event" << endl;
return;
}
try
{
m_timer_signal.emit();
}
catch( std::exception& ex )
{
if( dlog->is_crit() )
dlog->crit() << myname << "(onTimer): " << ex.what() << endl;
}
}
// -------------------------------------------------------------------------
void ModbusTCPServer::onSocketResetTimeout( ev::async& watcher, int revents ) noexcept
{
if( EV_ERROR & revents )
{
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::onSocketResetTimeout): invalid event" << endl;
return;
}
return;
}
try
{
m_timer_signal.emit();
}
catch( std::exception& ex )
{
if( dlog->is_crit() )
dlog->crit() << myname << "(onTimer): " << ex.what() << endl;
}
if( dlog->is_info() )
dlog->info() << myname << "(ModbusTCPServer::onSocketResetTimeout): reset socket timeout.." << endl;
if( sockTimeout.is_active() )
sockTimeout.again();
}
// -------------------------------------------------------------------------
void ModbusTCPServer::onSocketTimeout( ev::timer& t, int revents )
{
if (EV_ERROR & revents)
{
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): invalid event" << endl;
return;
}
{
std::lock_guard<std::mutex> l(sMutex);
if( !slist.empty())
{
if( dlog->is_info() )
dlog->info() << myname << "(ModbusTCPServer::onSocketTimeout): check socket [OK].." << endl;
t.again();
return;
}
}
if( dlog->is_warn() )
dlog->warn() << myname << "(ModbusTCPServer::onSocketTimeout): no connections.. recreate socket.." << endl;
try
{
createSocket();
if( io.is_active() )
io.stop();
io.start(sock->getSocket(), ev::READ);
}
catch( std::exception& ex )
{
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): recreate socket ERROR: " << ex.what() << endl;
}
t.again();
}
// -------------------------------------------------------------------------
mbErrCode ModbusTCPServer::realReceive( const std::unordered_set<ModbusAddr>& vaddr, timeout_t msecTimeout )
{
return ModbusRTU::erOperationFailed;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment