OSCAR-code/3rdparty/qtxmlrpc/server/src/protocol.cpp
Mark Watkins 392b0b5111 Separated QuaZip and QExtSerialPort, Oximetry work
Using official source which has been placed in 3rdparty folder
Oximetry button temporarily autostarts import.. Still a Work in progress.
2013-09-16 14:30:38 +10:00

392 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 );
}