/*************************************************************************** * Copyright (C) 2008 by Oliver Groß * * z.o.gross@gmx.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "csenderthread.h" #include #include #include #include namespace qftrans { CSenderThread::CSenderThread(QTcpSocket * socket, QObject * parent) : QThread(parent), m_Socket(socket), m_IdCounter(0) { } CSenderThread::~CSenderThread() { } void CSenderThread::addUpload(TransferData * upload) { if (!m_DataDict.contains(upload)) { qDebug() << "adding upload"; m_DataDict.insert(upload, m_IdCounter); m_IdCounter++; } } void CSenderThread::removeUpload(TransferData * transfer) { transfer->status = TS_CLOSING; if (m_Socket->bytesToWrite() == 0) { qDebug() << "executing upload"; writeData(); } } void CSenderThread::startUpload(TransferData * upload) { if (m_DataDict.contains(upload) && upload->status == TS_WAITING) { qDebug() << "scheduling upload for announce"; upload->status = TS_ANNOUNCING; if (m_Socket->bytesToWrite() == 0) { qDebug() << "executing upload"; writeData(); } } } void CSenderThread::startUploadData(quint32 id) { TransferData * transfer = m_DataDict.key(id); if (transfer) { qDebug() << "scheduling upload for transfer"; transfer->status = TS_TRANSFERING; if (m_Socket->bytesToWrite() == 0) { qDebug() << "executing upload"; writeData(); } } } void CSenderThread::sendAcknowledge(quint32 id) { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); TransferHeader header; // header.descriptor = DESCRIPTOR_STRING; header.type = HT_ACK; header.id = id; header.length = 0; out.writeRawData((const char *)(&header), sizeof(TransferHeader)); qDebug() << "sending HT_ACK" << id; m_Socket->write(block); } void CSendThread::writeData() { if (m_DataDict.isEmpty()) exit(); QByteArray block; QDataStream out(&block, QIODevice::ReadWrite); out.setVersion(QDataStream::Qt_4_0); QTransferDataList transfers = m_DataDict.keys(); QTransferDataList::iterator i; for (i = transfers.begin(); i != transfers.end(); ++i) { block.clear(); TransferHeader header; // header.descriptor = DESCRIPTOR_STRING; switch ((*i)->status) { case TS_ANNOUNCING: { qDebug() << "announcing" << m_DataDict[*i]; if ((*i)->transfered) (*i)->transfered = 0; // ID header with no data header.type = HT_ID; header.id = m_DataDict[*i]; header.length = 0; out.writeRawData((const char *)(&header), sizeof(TransferHeader)); //size header with size header.type = HT_SIZE; header.length = sizeof(qint64); out.writeRawData((const char *)(&header), sizeof(TransferHeader)); qDebug() << "sending size" << (*i)->size; out << (*i)->size; //name header with file name qint64 oldPosition = block.size(); //fake write filename out << (*i)->fileName; out.device()->seek(oldPosition); header.type = HT_NAME; header.length = quint32(block.size() - oldPosition); // qDebug() << "pos" << out.device()->pos() << block.size(); out.writeRawData((const char *)(&header), sizeof(TransferHeader)); // qDebug() << "pos post header" << out.device()->pos() << block.size(); // qint64 oldPosition = block.size() - sizeof(quint32); qDebug() << "sending filename" << (*i)->fileName; out << (*i)->fileName; // qDebug() << "pos post filename" << out.device()->pos() << block.size(); // out.device()->seek(oldPosition); // qDebug() << "pos post seek" << out.device()->pos(); /* qDebug() << "filename data length" << header.length; out << header.length; out.device()->seek(oldPosition); out >> header.length; qDebug() << "written length" << header.length; out.device()->seek(block.size()); qDebug() << "pos post length correct" << out.device()->pos() << block.size();*/ (*i)->status = TS_WAITING; } break; case TS_TRANSFERING: { // qDebug() << "transfering" << m_DataDict[*i]; header.type = HT_DATA; header.id = m_DataDict[*i]; if ((*i)->transfered + DATA_BLOCK_SIZE < (*i)->size) header.length = DATA_BLOCK_SIZE; else header.length = (*i)->size - (*i)->transfered; out.writeRawData((const char *)(&header), sizeof(TransferHeader)); char * buffer = new char[header.length]; QFile file((*i)->fileDir + (*i)->fileName); file.open(QIODevice::ReadOnly); QDataStream in(&file); in.readRawData(buffer, header.length); out.writeRawData((const char *)(buffer), header.length); (*i)->transfered += header.length; delete[] buffer; if ((*i)->transfered >= (*i)->size) (*i)->status = TS_CLOSING; emit uploadUpdated(*i); } break; case TS_CLOSING: header.type = HT_CLOSE; header.id = m_DataDict[*i]; header.length = 0; out.writeRawData((const char *)(&header), sizeof(TransferHeader)); (*i)->status = TS_FINISHED; m_DataDict.remove(*i); break; default: break; } if (!block.isEmpty()) m_Socket->write(block); } } void CSendThread::run() { qDebug() << "start sender thread"; connect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData())); exec(); disconnect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData())); } }