mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-17 19:20:46 +00:00
Using official source which has been placed in 3rdparty folder Oximetry button temporarily autostarts import.. Still a Work in progress.
392 lines
12 KiB
C++
392 lines
12 KiB
C++
#include "protocol.h"
|
||
|
||
QString ClientProtocol::unconnectedNoDstHost = QString("socket unconnected, no dstHost");
|
||
|
||
ClientProtocol::ClientProtocol( QTcpSocket *parent,
|
||
const QString & _dstHost,
|
||
const quint16 _dstPort )
|
||
: QObject(parent), socket( parent ),
|
||
dstHost( _dstHost ), dstPort( _dstPort ),
|
||
protocolRetry( 0 ), maxProtocolRetries( 3 ), protocolStarted( false ),
|
||
disconnectFromSocketOnDoneFlag( false )
|
||
{
|
||
Q_ASSERT( socket );
|
||
|
||
// check, if no dstHost, socket must be in the ConnectedState
|
||
if( dstHost.isEmpty() &&
|
||
socket->state() != QAbstractSocket::ConnectedState ) {
|
||
qCritical() << this << "constructor, dstHost.isEmpty(), but socket state"
|
||
<< socket->state();
|
||
qFatal( "you must check socket state, before creating protocol" );
|
||
}
|
||
connectTimeoutTimer = new QTimer( this );
|
||
connectTimeoutTimer->setSingleShot( true );
|
||
connect( connectTimeoutTimer, SIGNAL( timeout() ),
|
||
SLOT( slotSocketConnectTimeout() ) );
|
||
reconnectSleepTimer = new QTimer( this );
|
||
reconnectSleepTimer->setSingleShot( true );
|
||
connect( reconnectSleepTimer, SIGNAL( timeout() ),
|
||
SLOT( deferredStart() ) );
|
||
|
||
// connect socket signals to my slots
|
||
connect( socket, SIGNAL( error(QAbstractSocket::SocketError) ),
|
||
SLOT( slotSocketError(QAbstractSocket::SocketError) ) );
|
||
connect( socket, SIGNAL( stateChanged(QAbstractSocket::SocketState) ),
|
||
SLOT( slotSocketStateChanged(QAbstractSocket::SocketState) ) );
|
||
}
|
||
|
||
|
||
void ClientProtocol::slotSocketStateChanged ( QAbstractSocket::SocketState socketState )
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "slotSocketStateChanged(" << socketState << ")";
|
||
#endif
|
||
// Не слишком ли много мы ходили в protocolStart?
|
||
if( protocolRetry >= maxProtocolRetries ) {
|
||
emitError( "maxProtocolRetries reached" );
|
||
return;
|
||
}
|
||
|
||
switch( socketState ) {
|
||
case QAbstractSocket::ConnectedState:
|
||
// уже соединены, запускаем протокол
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "slotSocketStateChanged((): connected!"
|
||
<< "protocolRetry" << protocolRetry;
|
||
#endif
|
||
protocolStart();
|
||
break;
|
||
case QAbstractSocket::UnconnectedState:
|
||
if( protocolStarted )
|
||
protocolStop();
|
||
|
||
// can reconnect?
|
||
if( dstHost.size() ) {
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this
|
||
<< "slotSocketStateChanged(): starting reconnect timer...";
|
||
#endif
|
||
reconnectSleepTimer->start( reconnectSleep );
|
||
}
|
||
else
|
||
emitError( unconnectedNoDstHost );
|
||
break;
|
||
default:
|
||
; // do nothing
|
||
}
|
||
}
|
||
|
||
|
||
void ClientProtocol::slotSocketError( QAbstractSocket::SocketError socketError )
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "slotSocketError(" << socketError << ")";
|
||
#endif
|
||
switch( socketError ) {
|
||
case QAbstractSocket::ConnectionRefusedError:
|
||
case QAbstractSocket::SocketTimeoutError:
|
||
case QAbstractSocket::RemoteHostClosedError:
|
||
// ну чо поделать, как только socketState
|
||
// поменяется в UnconnectedState, начнется новый deferredStart
|
||
break;
|
||
case QAbstractSocket::HostNotFoundError:
|
||
qWarning() << this << "slotSocketError(): host not found"
|
||
<< dstHost << ":" << dstPort;
|
||
emitError( QString("host not found: ") +
|
||
dstHost + ":" + QString::number(dstPort) );
|
||
break;
|
||
case QAbstractSocket::SocketAccessError:
|
||
case QAbstractSocket::SocketResourceError:
|
||
case QAbstractSocket::DatagramTooLargeError:
|
||
case QAbstractSocket::AddressInUseError:
|
||
case QAbstractSocket::NetworkError:
|
||
case QAbstractSocket::SocketAddressNotAvailableError:
|
||
case QAbstractSocket::UnsupportedSocketOperationError:
|
||
case QAbstractSocket::ProxyAuthenticationRequiredError:
|
||
case QAbstractSocket::UnknownSocketError:
|
||
qCritical() << this << "slotSocketError(): bad socket error, aborting"
|
||
<< socketError;
|
||
emitError( "bad socket error" );
|
||
break;
|
||
default:
|
||
qCritical() << this << "slotSocketError(): unknown socket error"
|
||
<< socketError;
|
||
emitError( "Unknown socket error" );
|
||
}
|
||
}
|
||
|
||
|
||
void ClientProtocol::slotSocketConnectTimeout()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "slotSocketConnectTimeout()";
|
||
#endif
|
||
emitError( "socket connect timeout" );
|
||
}
|
||
|
||
|
||
void ClientProtocol::deferredStart()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "deferredStart()";
|
||
#endif
|
||
// Не слишком ли много мы ходили в protocolStart?
|
||
if( protocolRetry >= maxProtocolRetries ) {
|
||
emitError( "maxProtocolRetries reached" );
|
||
return;
|
||
}
|
||
|
||
// Не запущен timeoutTimer?
|
||
if( ! connectTimeoutTimer->isActive() )
|
||
connectTimeoutTimer->start( connectTimeout );
|
||
|
||
// запущен reconnectSleepTimer?
|
||
if( reconnectSleepTimer->isActive() )
|
||
reconnectSleepTimer->stop();
|
||
|
||
switch( socket->state() ) {
|
||
case QAbstractSocket::UnconnectedState:
|
||
// еще никуда не коннектится, начнем :)
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "deferredStart(): socket->connectToHost("
|
||
<< dstHost << "," << dstPort << ")";
|
||
#endif
|
||
if( dstHost.size() )
|
||
connectSocket();
|
||
else
|
||
emitError( "dstHost is empty and socket unconnected" );
|
||
break;
|
||
case QAbstractSocket::ConnectedState:
|
||
// уже соединены, запускаем протокол
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "deferredStart(): connected! protocolRetry"
|
||
<< protocolRetry;
|
||
#endif
|
||
protocolStart();
|
||
break;
|
||
default:
|
||
; // do nothing
|
||
}
|
||
}
|
||
|
||
|
||
void ClientProtocol::connectSocket()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocol::connectSocket()";
|
||
#endif
|
||
|
||
Q_ASSERT( dstHost.size() );
|
||
socket->connectToHost( dstHost, dstPort );
|
||
}
|
||
|
||
|
||
#ifdef DEBUG_PROTOCOL
|
||
void ClientProtocol::slotBytesWritten ( qint64 bytes )
|
||
{
|
||
qDebug() << this << "ClientProtocol::slotBytesWritten(" << bytes << ")";
|
||
#else
|
||
void ClientProtocol::slotBytesWritten ( qint64 )
|
||
{
|
||
#endif
|
||
}
|
||
|
||
|
||
void ClientProtocol::slotReadyRead()
|
||
{
|
||
// default implementation just read all data
|
||
QByteArray data = socket->readAll();
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocol::slotReadyRead(): " << data;
|
||
#endif
|
||
}
|
||
|
||
|
||
void ClientProtocol::emitError( const QString & errTxt )
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "emitError(" << errTxt << ")";
|
||
#endif
|
||
|
||
if( protocolStarted )
|
||
protocolStop();
|
||
else
|
||
stopTimers();
|
||
|
||
// disconnect all signals to me
|
||
socket->disconnect( this );
|
||
socket->abort();
|
||
|
||
emit error( errTxt );
|
||
}
|
||
|
||
|
||
void ClientProtocol::emitDone()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "emitDone()";
|
||
#endif
|
||
|
||
if( protocolStarted )
|
||
protocolStop();
|
||
else
|
||
stopTimers();
|
||
|
||
if( disconnectFromSocketOnDoneFlag )
|
||
socket->disconnect( this );
|
||
|
||
emit done();
|
||
}
|
||
|
||
|
||
void ClientProtocol::sureWrite( const QByteArray & response )
|
||
{
|
||
qint64 len = response.size();
|
||
const char * ptr = response.data();
|
||
while( len ) {
|
||
qint64 res = socket->write( ptr, len );
|
||
if ( res < 0 )
|
||
break;
|
||
len -= res;
|
||
ptr += res;
|
||
}
|
||
socket->flush();
|
||
}
|
||
|
||
|
||
void ClientProtocol::stopTimers()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocol::stopTimers()";
|
||
#endif
|
||
// stop my timers
|
||
if( connectTimeoutTimer->isActive() )
|
||
connectTimeoutTimer->stop();
|
||
|
||
if( reconnectSleepTimer->isActive() )
|
||
reconnectSleepTimer->stop();
|
||
}
|
||
|
||
|
||
void ClientProtocol::protocolStop()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocol::protocolStop()";
|
||
#endif
|
||
protocolStarted = false;
|
||
// disconnect socket data signals from protocol handlers
|
||
disconnect( socket, SIGNAL( readyRead() ),
|
||
this, SLOT( slotReadyRead() ) );
|
||
disconnect( socket, SIGNAL( bytesWritten(qint64) ),
|
||
this, SLOT( slotBytesWritten(qint64) ) );
|
||
}
|
||
|
||
|
||
void ClientProtocol::protocolStart()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocol::protocolStart()";
|
||
#endif
|
||
stopTimers();
|
||
|
||
protocolRetry++;
|
||
protocolStarted = true;
|
||
// connect socket data signals to protocol handlers
|
||
connect( socket, SIGNAL( readyRead() ),
|
||
this, SLOT( slotReadyRead() ) );
|
||
connect( socket, SIGNAL( bytesWritten(qint64) ),
|
||
this, SLOT( slotBytesWritten(qint64) ) );
|
||
|
||
// noProxyMode?
|
||
if( !qstrcmp(metaObject()->className(), "ClientProtocol") )
|
||
emitDone();
|
||
}
|
||
|
||
|
||
ClientProtocolWithTimeout::ClientProtocolWithTimeout( QTcpSocket * parent,
|
||
const int _protocolTimeout,
|
||
const QString & dstHost,
|
||
const quint16 dstPort )
|
||
: ClientProtocol( parent, dstHost, dstPort ),
|
||
protocolTimeout( _protocolTimeout )
|
||
{
|
||
protocolTimeoutTimer = new QTimer( this );
|
||
protocolTimeoutTimer->setSingleShot( true );
|
||
connect( protocolTimeoutTimer, SIGNAL( timeout() ),
|
||
SLOT( slotProtocolTimeout() ) );
|
||
}
|
||
|
||
|
||
void ClientProtocolWithTimeout::protocolStop()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocolWithTimeout::protocolStop():"
|
||
<< "stop protocol timeout timer";
|
||
#endif
|
||
ClientProtocol::protocolStop();
|
||
|
||
if( protocolTimeoutTimer->isActive() )
|
||
protocolTimeoutTimer->stop();
|
||
}
|
||
|
||
|
||
void ClientProtocolWithTimeout::protocolStart()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocolWithTimeout::protocolStart():"
|
||
<< "start protocol timeout timer"
|
||
<< protocolTimeout / 1000 << "secs";
|
||
#endif
|
||
ClientProtocol::protocolStart();
|
||
|
||
protocolTimeoutTimer->start( protocolTimeout );
|
||
}
|
||
|
||
|
||
void ClientProtocolWithTimeout::slotProtocolTimeout()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocolWithTimeout::slotProtocolTimeout()";
|
||
#endif
|
||
if( !objectName().length() ) {
|
||
qCritical() << this << "ClientProtocolWithTimeout::slotProtocolTimeout():"
|
||
<< "protocol name empty!"
|
||
<< "Please setObjectName() for your protocols!";
|
||
qFatal( "programming error" );
|
||
}
|
||
emitError( objectName() + " protocol timeout" );
|
||
}
|
||
|
||
|
||
#ifdef DEBUG_PROTOCOL
|
||
void ClientProtocolWithTimeout::slotBytesWritten( qint64 bytes )
|
||
{
|
||
qDebug() << this << "ClientProtocolWithTimeout::slotBytesWritten("
|
||
<< bytes << "): restart protocol timeout timer"
|
||
<< protocolTimeout / 1000 << "secs";
|
||
#else
|
||
void ClientProtocolWithTimeout::slotBytesWritten( qint64 )
|
||
{
|
||
#endif
|
||
Q_ASSERT( protocolStarted );
|
||
Q_ASSERT( protocolTimeoutTimer->isActive() );
|
||
|
||
// restart timeout timer.
|
||
protocolTimeoutTimer->start( protocolTimeout );
|
||
}
|
||
|
||
|
||
void ClientProtocolWithTimeout::slotReadyRead()
|
||
{
|
||
#ifdef DEBUG_PROTOCOL
|
||
qDebug() << this << "ClientProtocolWithTimeout::slotReadyRead():"
|
||
<< "restart protocol timeout timer"
|
||
<< protocolTimeout / 1000 << "secs";
|
||
#endif
|
||
Q_ASSERT( protocolStarted );
|
||
Q_ASSERT( protocolTimeoutTimer->isActive() );
|
||
|
||
// restart timeout timer.
|
||
protocolTimeoutTimer->start( protocolTimeout );
|
||
}
|