File indexing completed on 2024-05-05 05:40:32

0001 /************************************************************************
0002  *   Copyright (C) 2007 by Romain Campioni                               *
0003  *   Copyright (C) 2009 by Renaud Guezennec                              *
0004  *   Copyright (C) 2011 by Joseph Boudou                                 *
0005  *                                                                       *
0006  *     https://rolisteam.org/                                         *
0007  *                                                                       *
0008  *   Rolisteam is free software; you can redistribute it and/or modify   *
0009  *   it under the terms of the GNU General Public License as published   *
0010  *   by the Free Software Foundation; either version 2 of the License,   *
0011  *   or (at your option) any later version.                              *
0012  *                                                                       *
0013  *   This program is distributed in the hope that it will be useful,     *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of      *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
0016  *   GNU General Public License for more details.                        *
0017  *                                                                       *
0018  *   You should have received a copy of the GNU General Public License   *
0019  *   along with this program; if not, write to the                       *
0020  *   Free Software Foundation, Inc.,                                     *
0021  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           *
0022  *************************************************************************/
0023 #include "network/clientconnection.h"
0024 
0025 #include <QCoreApplication>
0026 #include <QTcpSocket>
0027 
0028 
0029 #include <QDebug>
0030 
0031 QByteArray dataToArray(const NetworkMessageHeader& header, const char* buffer)
0032 {
0033     QByteArray array;
0034     array.append(reinterpret_cast<const char*>(&header), sizeof(NetworkMessageHeader));
0035     array.append(buffer, static_cast<int>(header.dataSize));
0036     return array;
0037 }
0038 
0039 ClientConnection::ClientConnection() : m_socketTcp(new QTcpSocket(this))
0040 {
0041     m_socketTcp->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
0042     connect(m_socketTcp, &QTcpSocket::connected, this, [this]() { setConnected(true); });
0043     connect(m_socketTcp, &QTcpSocket::disconnected, this, [this]() { setConnected(false); });
0044     connect(m_socketTcp, &QTcpSocket::readyRead, this, &ClientConnection::receivingData);
0045     connect(m_socketTcp, &QTcpSocket::bytesWritten, this, [](qint64 bytes) { qDebug() << bytes << "byteWrittens"; });
0046     connect(m_socketTcp, &QTcpSocket::stateChanged, this, [](const QAbstractSocket::SocketState& state) {
0047         qDebug() << "NetworkLink - state changed" << state;
0048         /*switch(state)
0049         {
0050         case QAbstractSocket::ClosingState:
0051         case QAbstractSocket::UnconnectedState:
0052         case QAbstractSocket::HostLookupState:
0053         case QAbstractSocket::ConnectingState:
0054         case QAbstractSocket::BoundState:
0055             break;
0056         case QAbstractSocket::ConnectedState:
0057             qDebug() << "socket state Connected";
0058             break;
0059         default:
0060             break;
0061         }*/
0062     });
0063 
0064     connect(m_socketTcp, &QTcpSocket::errorOccurred, this, [this](const QAbstractSocket::SocketError& error) {
0065         qDebug() << "NetworkLink - state changed" << error << m_socketTcp->errorString();
0066         if(m_socketTcp.isNull())
0067             return;
0068         emit errorOccured(m_socketTcp->errorString());
0069     });
0070 
0071     m_receivingData= false;
0072     m_headerRead= 0;
0073 }
0074 ClientConnection::~ClientConnection()= default;
0075 
0076 bool ClientConnection::connected() const
0077 {
0078     return m_connected;
0079 }
0080 
0081 void ClientConnection::sendData(char* data, qint64 size)
0082 {
0083     if(!m_connected)
0084         return;
0085 
0086     if(nullptr == m_socketTcp)
0087     {
0088         emit errorOccured(tr("Socket is null"));
0089         return;
0090     }
0091     if(!m_socketTcp->isWritable())
0092     {
0093         emit errorOccured(tr("Socket is not writable"));
0094         return;
0095     }
0096 
0097     // sending data
0098 #ifdef DEBUG_MODE
0099     NetworkMessageHeader header;
0100     memcpy(reinterpret_cast<char*>(&header), data, sizeof(NetworkMessageHeader));
0101     qDebug() << "send Data Categorie:" << MessageDispatcher::cat2String(reinterpret_cast<NetworkMessageHeader*>(data))
0102              << "Action" << MessageDispatcher::act2String(reinterpret_cast<NetworkMessageHeader*>(data));
0103 
0104     qDebug() << "header: cat" << header.category << "act:" << header.action << "datasize:" << header.dataSize << "size"
0105              << size << static_cast<int>(data[0]) << "socket" << m_socketTcp;
0106 
0107     qDebug() << "thread current" << QThread::currentThread() << "thread socket:" << m_socketTcp->thread()
0108              << "this thread" << thread();
0109 #endif
0110 
0111     qDebug() << size;
0112     auto t= m_socketTcp->write(data, size);
0113 
0114     if(t < 0)
0115     {
0116         emit errorOccured(tr("Transmission error :") + m_socketTcp->errorString());
0117     }
0118 }
0119 
0120 void ClientConnection::sendMessage(const NetworkMessage* msg)
0121 {
0122     if(!m_connected)
0123         return;
0124 
0125     sendData(reinterpret_cast<char*>(msg->buffer()), static_cast<qint64>(msg->getSize()));
0126 }
0127 
0128 void ClientConnection::receivingData()
0129 {
0130     if(nullptr == m_socketTcp)
0131     {
0132         return;
0133     }
0134     qint64 readData= 0;
0135 
0136     while(m_socketTcp->bytesAvailable())
0137     {
0138         if(!m_receivingData)
0139         {
0140             qint64 readDataSize= 0;
0141             char* tmp= reinterpret_cast<char*>(&m_header);
0142             readDataSize= m_socketTcp->read(tmp + m_headerRead, static_cast<qint64>(sizeof(NetworkMessageHeader))
0143                                                                     - static_cast<qint64>(m_headerRead));
0144             readDataSize+= static_cast<qint64>(m_headerRead);
0145 
0146             if((readDataSize
0147                 != static_cast<qint64>(sizeof(NetworkMessageHeader)))) //||(m_header.category>=NetMsg::LastCategory)
0148             {
0149                 m_headerRead= static_cast<quint64>(readDataSize);
0150                 return;
0151             }
0152             else
0153             {
0154                 m_headerRead= 0;
0155             }
0156             m_buffer= new char[m_header.dataSize];
0157             m_remainingData= m_header.dataSize;
0158             emit readDataReceived(m_header.dataSize, m_header.dataSize);
0159         }
0160         readData
0161             = m_socketTcp->read(&(m_buffer[m_header.dataSize - m_remainingData]), static_cast<qint64>(m_remainingData));
0162         if(readData < static_cast<qint64>(m_remainingData))
0163         {
0164             m_remainingData-= static_cast<quint32>(readData);
0165             m_receivingData= true;
0166             emit readDataReceived(m_remainingData, m_header.dataSize);
0167         }
0168         else
0169         {
0170             emit readDataReceived(0, 0);
0171             auto array= dataToArray(m_header, m_buffer);
0172             emit messageReceived(array);
0173 
0174             delete[] m_buffer;
0175             m_remainingData= 0;
0176             m_receivingData= false;
0177         }
0178     }
0179 }
0180 
0181 void ClientConnection::closeCommunicationWithServer()
0182 {
0183     if(nullptr == m_socketTcp)
0184         return;
0185 
0186     m_socketTcp->disconnectFromHost();
0187 }
0188 
0189 void ClientConnection::connectTo(const QString& host, int port)
0190 {
0191     qDebug() << "Connect To" << host << port << m_socketTcp.isNull();
0192     if(m_socketTcp.isNull())
0193         return;
0194 
0195     m_socketTcp->connectToHost(host, static_cast<quint16>(port));
0196 }
0197 
0198 void ClientConnection::setConnected(bool b)
0199 {
0200     if(b == m_connected)
0201         return;
0202     m_connected= b;
0203     emit connectedChanged(b);
0204 }
0205 
0206 void ClientConnection::reset()
0207 {
0208     m_inError= false;
0209     m_connected= false;
0210 }