218 lines
6.7 KiB
C++
218 lines
6.7 KiB
C++
/***************************************************************************
|
|
* 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 <QTcpSocket>
|
|
#include <QByteArray>
|
|
#include <QDataStream>
|
|
#include <QFile>
|
|
|
|
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()));
|
|
}
|
|
|
|
}
|