/* **************************************************************************** * Copyright 2019 Open Systems Development BV * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * * DEALINGS IN THE SOFTWARE. * * ***************************************************************************/ #include "tcpsocket.h" #include "log.h" #include #include #include #include namespace osdev { namespace components { TcpSocket::TcpSocket( const QString& ipAddress, int portNumber ) : m_pSocket(new QTcpSocket(this)) , m_blockSize(0) , m_dataBuffer() , m_pTimer( new QTimer() ) { // First we connect the timer to this class connect(m_pTimer.get(), SIGNAL(timeout()), this, SLOT(chkSendBuffer())); this->connectSocketSignals(); m_pSocket->connectToHost( QHostAddress( ipAddress ), static_cast(portNumber) ); if( !m_pSocket->waitForConnected( 3000 ) ) { LogDebug("interfaceplugin", "Socket failed to connect."); LogObject("interfaceplugin", this); } else { LogDebug("interfaceplugin", "Client connected : "); LogObject("interfaceplugin", m_pSocket); } } TcpSocket::TcpSocket(QTcpSocket *pSocket) : m_pSocket(pSocket) , m_blockSize(0) , m_dataBuffer() , m_pTimer( new QTimer() ) { Q_ASSERT(pSocket); connect(m_pTimer.get(), SIGNAL(timeout()), this, SLOT(chkSendBuffer())); this->connectSocketSignals(); } TcpSocket::~TcpSocket() { // Implicitly deletes m_pSocket if this object is its parent } void TcpSocket::slotReadyRead() { // Let the poolmanager know we are busy receiving data at the moment and are // unavailable for anything else. emit signalReceivingData( this ); QDataStream in( m_pSocket ); in.setVersion( QDataStream::Qt_5_4 ); if( m_blockSize == 0 ) { if( m_pSocket->bytesAvailable() < static_cast(sizeof( quint32 ) ) ) { return; } in >> m_blockSize; } if( m_pSocket->bytesAvailable() < m_blockSize ) { return; } in >> m_dataBuffer; emit signalDataReceived( m_dataBuffer, this ); m_blockSize = 0; // Reset the blockSize for next read. m_dataBuffer.clear(); // Reset the buffer for the next read. } void TcpSocket::slotSendData( const QString &sData, TcpSocket *pSocket ) { if( pSocket != this || sData.isNull() ) { return; } QByteArray block; QDataStream out( &block, QIODevice::WriteOnly ); out.setVersion( QDataStream::Qt_5_4 ); out << block.size(); out << sData; m_pSocket->write( block ); chkSendBuffer(); } void TcpSocket::slotSetSocket(QTcpSocket* pSocket ) { if(m_pSocket) { disconnectSocketSignals(); } m_pSocket = pSocket; connectSocketSignals(); } void TcpSocket::chkSendBuffer() { m_pTimer->stop(); if( m_pSocket->bytesToWrite() > 0 ) { m_pSocket->flush(); m_pTimer->start( 500 ); } else { emit signalDataSent( this ); } } void TcpSocket::slotConnected() { emit signalConnected( this ); } void TcpSocket::slotDisconnected() { emit signalDisconnected( this ); } QString TcpSocket::showError() { if( m_pSocket ) { return m_pSocket->errorString(); } else { return "No socket available"; } } void TcpSocket::connectSocketSignals() { Q_ASSERT(m_pSocket); // Connect the required signals and slots to gain control. // First for receiving data. connect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( slotReadyRead() ) ); connect( m_pSocket, SIGNAL( connected() ), this, SLOT( slotConnected() ) ); connect( m_pSocket, SIGNAL( disconnected() ), this, SLOT( slotDisconnected() ) ); } void TcpSocket::disconnectSocketSignals() { Q_ASSERT(m_pSocket); // Connect the required signals and slots to gain control. // First for receiving data. disconnect( m_pSocket, SIGNAL( readyRead() ), this, SLOT( slotReadyRead() ) ); disconnect( m_pSocket, SIGNAL( connected() ), this, SLOT( slotConnected() ) ); disconnect( m_pSocket, SIGNAL( disconnected() ), this, SLOT( slotDisconnected() ) ); } bool TcpSocket::isConnected() { return m_pSocket && m_pSocket->state() == QTcpSocket::ConnectedState; } } }