#include "sendsystem.h" SendSystem::SendSystem(QObject *parent) : QObject(parent) { qDebug() << "SendSystem init thread ID " << QThread::currentThreadId(); client = nullptr; socket = nullptr; dataParser = nullptr; globalMutex = nullptr; waitCondition = nullptr; buffer = nullptr; type = TypeClientAutorization::TYPE_GUI; isSendStopped = false; flWaitWriten = false; fileSize = 0; countSend = 0; buffer = new char[sendFileBlockSize]; } SendSystem::~SendSystem() { delete buffer; } void SendSystem::initialize(DataParser *dataParser,QMutex *globalMutex) { qDebug() << "SendSystem::initialize thread ID " << QThread::currentThreadId(); this->dataParser = dataParser; this->globalMutex = globalMutex; connect(this,&SendSystem::sigSendNotify,dataParser->ClientAnswer(),&ClientAnswerParser::notify,Qt::DirectConnection); //потому что возвращает значение } void SendSystem::setClient(Client *client,QTcpSocket *socket) { qDebug() << "SendSystem::setClient thread ID " << QThread::currentThreadId(); this->socket = socket; this->client = client; this->type = client->getClientType(); isSendStopped = false; } void SendSystem::sendNotify(QString notify) { qDebug() << "SendSystem::sendNotify thread ID " << QThread::currentThreadId(); auto answer = emit sigSendNotify(notify); sendXmlAnswer(answer); } void SendSystem::sendFileBlock(QString path) { //qDebug() << "SendSystem::sendFileBlock path: " << path; if(getIsSendStopped()) { //Поведение на случай отключения клиента Logger::instance().log("Client: " + client->getLogin() + " isSendStopped", LogLevel::ERROR); return; } QFile file(path); QFileInfo fileInfo(file); fileSize = file.size(); if (fileSize == 0) { Logger::instance().log("Client: " + client->getLogin() + " ERROR! File zero size " + fileInfo.fileName(), LogLevel::ERROR); Logger::instance().log(path, LogLevel::ERROR); return; } if(!file.open(QFile::ReadOnly)) { Logger::instance().log("Client: " + client->getLogin() + " ERROR! File not open: " + fileInfo.fileName(), LogLevel::ERROR); Logger::instance().log(path, LogLevel::ERROR); return; } countSend = 0; QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_FILE; //Отправляем тип блока stream << path << fileSize; waitWrittenData("sendFileBlock:header " + fileInfo.fileName()); while(!file.atEnd()) { QByteArray data = file.read(sendFileBlockSize); stream << data; waitWrittenData(QString("sendFileBlock:data (size %1) ").arg(data.size()) + fileInfo.fileName()); if(socket->state() == QAbstractSocket::UnconnectedState) { Logger::instance().log("Client: " + client->getLogin() + " UnconnectedState", LogLevel::ERROR); break; } countSend++; } file.close(); countSend = 0; } void SendSystem::sendFileBlock_V2(QString path) { QFile file(path); if(!file.open(QIODevice::ReadOnly)) { Logger::instance().log("ERROR open file: " + path, LogLevel::ERROR); return; } countSend = 0; fileSize = file.size(); if (fileSize == 0) { Logger::instance().log("Client: " + client->getLogin() + " WARNING! Zero size " +file.fileName(), LogLevel::ERROR); Logger::instance().log(path, LogLevel::ERROR); return; } QString type = QString::number(PacketType::TYPE_FILE); QString fileSizeStr = QString::number(fileSize); qDebug() << "SendSystem::sendFileBlock_V2 file " << file.fileName() << " size " << fileSizeStr; QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); //mutexWriten.lock(); //flWaitWriten = true; stream << PacketType::TYPE_FILE; //Отправляем тип блока stream << path << fileSize; socket->waitForBytesWritten(10); /* while(flWaitWriten) { QCoreApplication::processEvents(); // Обеспечиваем обработку сообщений } */ //socket->waitForBytesWritten(10); //socket->write(type.toUtf8()); //socket->write(fileSizeStr.toUtf8()); connect(this->socket, &QTcpSocket::bytesWritten, this, &SendSystem::slot_BytesWrittenToSocket); while(true) { if(socket->state() == QAbstractSocket::UnconnectedState) break; countSend++; qint64 readBytes = file.read(buffer, /*sizeof(buffer)*/sendFileBlockSize); if(readBytes <= 0) break; flWaitWriten = true; while(!socket->write(buffer, readBytes)) { int i = 0; i++; } while(flWaitWriten) { QCoreApplication::processEvents(); // Обеспечиваем обработку сообщений } /* while(!socket->flush()) { int i = 0; i++; } */ // Завершаем отправку //socket->flush(); //socket->waitForBytesWritten(10); } disconnect(this->socket, &QTcpSocket::bytesWritten, this, &SendSystem::slot_BytesWrittenToSocket); //socket->flush(); /* while(!socket->flush()) { int i = 0; i++; }*/ file.close(); } void SendSystem::sendFileBlock_V3(QString path) { //qDebug() << "SendSystem::sendFileBlock path: " << path; if(getIsSendStopped()) { //Поведение на случай отключения клиента Logger::instance().log("Client: " + client->getLogin() + " isSendStopped", LogLevel::ERROR); return; } QFile file(path); QFileInfo fileInfo(file); fileSize = file.size(); if (fileSize == 0) { Logger::instance().log("Client: " + client->getLogin() + " ERROR! File zero size " + fileInfo.fileName(), LogLevel::ERROR); Logger::instance().log(path, LogLevel::ERROR); return; } if(!file.open(QFile::ReadOnly)) { Logger::instance().log("Client: " + client->getLogin() + " ERROR! File not open: " + fileInfo.fileName(), LogLevel::ERROR); Logger::instance().log(path, LogLevel::ERROR); return; } countSend = 0; QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_FILE; //Отправляем тип блока stream << path << fileSize; waitWrittenData("sendFileBlock:header " + fileInfo.fileName()); connect(this->socket, &QTcpSocket::bytesWritten, this, &SendSystem::slot_BytesWrittenToSocket); while(!file.atEnd()) { if(socket->state() == QAbstractSocket::UnconnectedState) { Logger::instance().log("Client: " + client->getLogin() + " UnconnectedState", LogLevel::ERROR); break; } qint64 readBytes = file.read(buffer, /*sizeof(buffer)*/sendFileBlockSize); if(readBytes <= 0) break; flWaitWriten = true; while(!socket->write(buffer, readBytes)) { int i = 0; i++; qCritical() << "socket->write ERROR. size " + QString::number(readBytes); } while(flWaitWriten) { QCoreApplication::processEvents(); // Обеспечиваем обработку сообщений int i = 0; i++; } waitWrittenData(QString("sendFileBlock:data (readBytes %1, num %2) ").arg(QString::number(readBytes), QString::number(countSend)) + fileInfo.fileName()); countSend++; } disconnect(this->socket, &QTcpSocket::bytesWritten, this, &SendSystem::slot_BytesWrittenToSocket); file.close(); countSend = 0; } void SendSystem::sendFileBlockByteArray(QByteArray array, PacketType packetType) { if(client->getClientType() == TypeClientAutorization::TYPE_QT_CLIENT || client->getClientType() == TypeClientAutorization::TYPE_GUI) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); qint64 size = array.size(); qint64 bytesSended = 0; if (size == 0) { Logger::instance().log(" WARNING! Zero size ",LogLevel::ERROR); return; } stream << packetType; //Отправляем тип блока stream << size; socket->waitForBytesWritten(10); while (bytesSended < size) { QByteArray chunk = array.mid(bytesSended,sendFileBlockSize); stream << chunk; socket->waitForBytesWritten(10); bytesSended += chunk.length(); } } else { sendPacketType(packetType); qint64 size = array.size(); qint64 bytesSended = 0; if (size == 0) { Logger::instance().log(" WARNING! Zero size ",LogLevel::ERROR); return; } QByteArray message; message.append(reinterpret_cast(&size), sizeof(int)); socket->write(message); while (size > 0) { QByteArray chunk = array.mid(bytesSended,sendFileBlockSize); bytesSended = socket->write(chunk); size -= bytesSended; } } } void SendSystem::sendVersion() { QByteArray data = dataParser->ClientAnswer()->currentVersion(); sendXmlAnswer(data); } void SendSystem::slot_BytesWrittenToSocket(qint64 bytes) { flWaitWriten = false; } void SendSystem::sendFileBlockWithRename(QString path, QString newName) { qDebug() << "SendSystem::sendFileBlockWithRename thread ID " << QThread::currentThreadId(); QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); QFile file(Tools::createRootPath(path)); QFileInfo fileInfo(file); fileSize = fileInfo.size(); if(fileSize == 0){ Logger::instance().log("Client: " + client->getLogin() + " WARNING! Zero size " + fileInfo.fileName(),LogLevel::ERROR); return; } QString pathForSend = Tools::createFolderPath(path) + "/" + staticDataFolderName + newName; stream << PacketType::TYPE_FILE; //Отправляем тип блока stream << pathForSend << fileSize; socket->waitForBytesWritten(10); if(isSendStopped) { //Поведение на случай отключения клиента file.close(); return; } //socket->waitForBytesWritten(); if(file.open(QFile::ReadOnly)){ while(!file.atEnd()){ QByteArray data = file.read(sendFileBlockSize); stream << data; socket->waitForBytesWritten(10); countSend++; } Logger::instance().log("Send file " + fileInfo.fileName()); } file.close(); countSend = 0; socket->waitForBytesWritten(10); //socket->waitForReadyRead(100); sendNotify(commandHashCompleteClient); } void SendSystem::sendFolderBlock(QString path) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_FOLDER; stream << path; waitWrittenData("sendFolderBlock"); } void SendSystem::sendDeleteBlock(QString path) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_DELETE; stream << path; waitWrittenData("sendDeleteBlock"); } void SendSystem::sendPacketType(PacketType packetType) { Logger::instance().log(" SEND TO: " + client->getLogin() + " " + enumToString(packetType), LogLevel::DEBUG); if (client->getClientType() == TypeClientAutorization::TYPE_QT_CLIENT || client->getClientType() == TypeClientAutorization::TYPE_GUI) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << packetType; waitWrittenData("sendPacketType"); } else { QByteArray message; int type = (int)packetType; message.append(reinterpret_cast(&type), sizeof(int)); socket->write(message); } } void SendSystem::sendXmlAnswer(QByteArray array, PacketType packetType) { qDebug() << "SendSystem::sendXmlAnswer thread ID " << QThread::currentThreadId(); Logger::instance().log("SEND TO: "+ client->getLogin() + " " + enumToString(packetType) + "\n Text: " + QString(array),LogLevel::DEBUG); if (client->getClientType() == TypeClientAutorization::TYPE_QT_CLIENT || client->getClientType() == TypeClientAutorization::TYPE_GUI) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << packetType; stream << array; waitWrittenData("sendXmlAnswer"); } else { sendPacketType(packetType); QByteArray message; int size = array.length(); message.append(reinterpret_cast(&size), sizeof(int)); socket->write(message); socket->write(array); } } void SendSystem::sendNeedUpdate(bool flag,quint64 size,quint64 fileCount,quint64 deleteCount) { QDataStream stream(socket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_NEEDUPDATE; stream << flag; stream << size; stream << fileCount; stream << deleteCount; waitWrittenData("sendNeedUpdate"); } void SendSystem::updateFiles(QList fileSendList, QList deleteList) { //globalMutex->lock(); QListIterator clientIterator(deleteList); while(clientIterator.hasNext()) { FileData data = clientIterator.next(); sendDeleteBlock(data.path); if(getIsSendStopped()) { Logger::instance().log("Client: " + client->getLogin() + " isSendStopped", LogLevel::ERROR); //globalMutex->unlock(); return; } } QListIterator serverIterator(fileSendList); while(serverIterator.hasNext()) { FileData data = serverIterator.next(); if (data.hash == "FOLDER") { sendFolderBlock(data.path); } else { sendFileBlock_V3(data.path); } if(getIsSendStopped()) { //globalMutex->unlock(); return; } } sendPacketType(PacketType::UPDATE_FILES_COMPLETE); //globalMutex->unlock(); } void SendSystem::socketClose() { socket->close(); } void SendSystem::sendStop() { isSendStopped = true; } void SendSystem::sendCFI(QByteArray array) { sendXmlAnswer(array,PacketType::TYPE_UPDATEDCFI); } void SendSystem::sendDocs(QString docsPath) { sendFileBlock(docsPath); } bool SendSystem::getIsSendStopped() const { return isSendStopped; } bool SendSystem::waitWrittenData(QString marker, int msec) { bool success = socket->waitForBytesWritten(msec); if(success) { //qInfo() << "Data sended OK. <" + marker + ">"; } else { qCritical() << "Data sended ERROR. <" + marker + ">"; } return success; }