You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.7 KiB
217 lines
6.7 KiB
/*************************************************************************** |
|
* 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())); |
|
} |
|
|
|
}
|
|
|