|
|
@ -38,44 +38,59 @@ namespace qftrans { |
|
|
|
|
|
|
|
//TODO addUpload
|
|
|
|
void CWorker::addUpload(TransferData * transfer) { |
|
|
|
if (!m_UploadDict.contains(transfer)) { |
|
|
|
transfer->status = TS_PENDING; |
|
|
|
|
|
|
|
if (!m_Uploads.contains(transfer)) { |
|
|
|
qDebug() << "adding upload"; |
|
|
|
transfer->status = TS_WAITING; |
|
|
|
m_UploadDict.insert(transfer, m_IdCounter); |
|
|
|
transfer->id = m_IdCounter; |
|
|
|
m_IdCounter++; |
|
|
|
m_Uploads.enqueue(transfer); |
|
|
|
} |
|
|
|
else |
|
|
|
qDebug() << "(re)adding upload"; |
|
|
|
|
|
|
|
if (m_Socket->bytesToWrite() == 0) { |
|
|
|
qDebug() << "executing upload"; |
|
|
|
writeData(); |
|
|
|
} |
|
|
|
} |
|
|
|
//TODO removeUpload
|
|
|
|
void CWorker::removeUpload(TransferData * transfer) { |
|
|
|
if (m_UploadDict.contains(transfer) && transfer->status != TS_WAITING) { |
|
|
|
if (m_Uploads.contains(transfer) && transfer->status > TS_PENDING) { |
|
|
|
transfer->status = TS_CLOSING; |
|
|
|
if (m_Socket->bytesToWrite() == 0) { |
|
|
|
qDebug() << "executing upload"; |
|
|
|
writeData(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
//TODO startUpload
|
|
|
|
void CWorker::startUpload(TransferData * transfer) { |
|
|
|
if (m_UploadDict.contains(transfer) && transfer->status == TS_WAITING) { |
|
|
|
qDebug() << "scheduling upload for announce"; |
|
|
|
transfer->status = TS_ANNOUNCING; |
|
|
|
if (m_Socket->bytesToWrite() == 0) { |
|
|
|
qDebug() << "executing upload"; |
|
|
|
qDebug() << "executing closedown"; |
|
|
|
writeData(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
//TODO ? startUpload
|
|
|
|
// void CWorker::startUpload(TransferData * transfer) {
|
|
|
|
// if (m_Uploads.contains(transfer) && transfer->status != TS_PENDING)
|
|
|
|
// transfer->status = TS_PENDING;
|
|
|
|
//
|
|
|
|
// if (m_Socket->bytesToWrite() == 0) {
|
|
|
|
// qDebug() << "executing upload";
|
|
|
|
// writeData();
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
void CWorker::startUploadData(quint32 id) { |
|
|
|
TransferData * transfer = m_UploadDict.key(id); |
|
|
|
if (transfer) { |
|
|
|
qDebug() << "scheduling upload for transfer"; |
|
|
|
transfer->status = TS_TRANSFERING; |
|
|
|
if (m_Socket->bytesToWrite() == 0) { |
|
|
|
qDebug() << "executing upload"; |
|
|
|
writeData(); |
|
|
|
} |
|
|
|
if (m_Uploads.isEmpty()) |
|
|
|
return; |
|
|
|
|
|
|
|
TransferData * transfer = m_Uploads.head(); /*m_UploadDict.key(id);*/ |
|
|
|
|
|
|
|
if (transfer->id != id) { |
|
|
|
qDebug() << "got invalid id:" << id << "... expected:" << transfer->id; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
qDebug() << "scheduling upload for transfer"; |
|
|
|
transfer->status = TS_TRANSFERING; |
|
|
|
if (m_Socket->bytesToWrite() == 0) { |
|
|
|
qDebug() << "executing upload"; |
|
|
|
writeData(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -85,7 +100,6 @@ namespace qftrans { |
|
|
|
out.setVersion(QDataStream::Qt_4_0); |
|
|
|
|
|
|
|
TransferHeader header; |
|
|
|
// header.descriptor = DESCRIPTOR_STRING;
|
|
|
|
|
|
|
|
header.type = HT_ACK; |
|
|
|
header.id = id; |
|
|
@ -109,141 +123,114 @@ namespace qftrans { |
|
|
|
} |
|
|
|
|
|
|
|
void CWorker::writeData() { |
|
|
|
if (m_UploadDict.isEmpty()) { |
|
|
|
if (m_Uploads.isEmpty()) { |
|
|
|
// if (m_UploadDict.isEmpty()) {
|
|
|
|
qDebug() << "no more uploads."; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
TransferData * transfer = m_Uploads.head(); |
|
|
|
|
|
|
|
if (transfer->status == TS_PENDING) |
|
|
|
transfer->status = TS_ANNOUNCING; |
|
|
|
|
|
|
|
QByteArray block; |
|
|
|
QDataStream out(&block, QIODevice::ReadWrite); |
|
|
|
out.setVersion(QDataStream::Qt_4_0); |
|
|
|
|
|
|
|
QTransferDataList transfers = m_UploadDict.keys(); |
|
|
|
QTransferDataList::iterator i; |
|
|
|
for (i = transfers.begin(); i != transfers.end(); ++i) { |
|
|
|
block.clear(); |
|
|
|
|
|
|
|
TransferHeader header; |
|
|
|
switch ((*i)->status) { |
|
|
|
case TS_ANNOUNCING: { |
|
|
|
qDebug() << "announcing" << m_UploadDict[*i]; |
|
|
|
if ((*i)->transfered) |
|
|
|
(*i)->transfered = 0; |
|
|
|
|
|
|
|
// ID header with no data
|
|
|
|
header.type = HT_ID; |
|
|
|
header.id = m_UploadDict[*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; |
|
|
|
TransferHeader header; |
|
|
|
switch (transfer->status) { |
|
|
|
case TS_ANNOUNCING: |
|
|
|
{ |
|
|
|
qDebug() << "announcing" << transfer->id; |
|
|
|
if (transfer->transfered) |
|
|
|
transfer->transfered = 0; |
|
|
|
|
|
|
|
qint64 oldPosition = block.size(); |
|
|
|
|
|
|
|
//fake write filename
|
|
|
|
out << transfer->fileName; |
|
|
|
out.device()->seek(oldPosition); |
|
|
|
|
|
|
|
// ANNOUNCE header with size and filename
|
|
|
|
header.type = HT_ANNOUNCE; |
|
|
|
header.id = transfer->id; |
|
|
|
header.length = quint32(block.size() - oldPosition) + sizeof(qint64); |
|
|
|
|
|
|
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader)); |
|
|
|
|
|
|
|
qDebug() << "sending size" << transfer->size; |
|
|
|
out << transfer->size; |
|
|
|
|
|
|
|
qDebug() << "sending filename" << transfer->fileName; |
|
|
|
out << transfer->fileName; |
|
|
|
|
|
|
|
transfer->status = TS_WAITING; |
|
|
|
} |
|
|
|
break; |
|
|
|
case TS_TRANSFERING: |
|
|
|
{ |
|
|
|
header.type = HT_DATA; |
|
|
|
header.id = transfer->id; |
|
|
|
if (transfer->transfered + DATA_BLOCK_SIZE < transfer->size) |
|
|
|
header.length = DATA_BLOCK_SIZE; |
|
|
|
else |
|
|
|
header.length = transfer->size - transfer->transfered; |
|
|
|
|
|
|
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader)); |
|
|
|
|
|
|
|
char * buffer = new char[header.length]; |
|
|
|
|
|
|
|
QFile file(transfer->fileDir + QDir::separator() + transfer->fileName); |
|
|
|
file.open(QIODevice::ReadOnly); |
|
|
|
QDataStream in(&file); |
|
|
|
if (in.skipRawData(transfer->transfered) == -1) { |
|
|
|
qDebug() << "filename" << file.fileName(); |
|
|
|
qDebug() << "skip error"; |
|
|
|
qDebug() << "file size" << transfer->size; |
|
|
|
qDebug() << "transfered bytes" << transfer->transfered; |
|
|
|
} |
|
|
|
break; |
|
|
|
case TS_TRANSFERING: { |
|
|
|
// qDebug() << "transfering" << m_DataDict[*i];
|
|
|
|
header.type = HT_DATA; |
|
|
|
header.id = m_UploadDict[*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 + QDir::separator() + (*i)->fileName); |
|
|
|
file.open(QIODevice::ReadOnly); |
|
|
|
QDataStream in(&file); |
|
|
|
if (in.skipRawData((*i)->transfered) == -1) { |
|
|
|
qDebug() << "filename" << file.fileName(); |
|
|
|
qDebug() << "skip error"; |
|
|
|
qDebug() << "file size" << (*i)->size; |
|
|
|
qDebug() << "transfered bytes" << (*i)->transfered; |
|
|
|
} |
|
|
|
// in.device()->seek((*i)->transfered);
|
|
|
|
if (in.readRawData(buffer, header.length) == -1) { |
|
|
|
qDebug() << "Read error"; |
|
|
|
qDebug() << "buffer size" << header.length; |
|
|
|
qDebug() << "file size" << (*i)->size; |
|
|
|
qDebug() << "transfered bytes" << (*i)->transfered; |
|
|
|
} |
|
|
|
|
|
|
|
out.writeRawData((const char *)(buffer), header.length); |
|
|
|
(*i)->transfered += header.length; |
|
|
|
delete[] buffer; |
|
|
|
|
|
|
|
if ((*i)->transfered >= (*i)->size) |
|
|
|
(*i)->status = TS_CLOSING; |
|
|
|
|
|
|
|
if ((*i)->transfered > (*i)->size) { |
|
|
|
qDebug() << "overread?"; |
|
|
|
qDebug() << "file size" << (*i)->size; |
|
|
|
qDebug() << "transfered bytes" << (*i)->transfered; |
|
|
|
} |
|
|
|
|
|
|
|
emit uploadUpdated(*i); |
|
|
|
if (in.readRawData(buffer, header.length) == -1) { |
|
|
|
qDebug() << "Read error"; |
|
|
|
qDebug() << "buffer size" << header.length; |
|
|
|
qDebug() << "file size" << transfer->size; |
|
|
|
qDebug() << "transfered bytes" << transfer->transfered; |
|
|
|
} |
|
|
|
break; |
|
|
|
case TS_CLOSING: |
|
|
|
header.type = HT_CLOSE; |
|
|
|
header.id = m_UploadDict[*i]; |
|
|
|
header.length = 0; |
|
|
|
|
|
|
|
out.writeRawData((const char *)(buffer), header.length); |
|
|
|
transfer->transfered += header.length; |
|
|
|
delete[] buffer; |
|
|
|
|
|
|
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader)); |
|
|
|
if (transfer->transfered >= transfer->size) |
|
|
|
transfer->status = TS_CLOSING; |
|
|
|
|
|
|
|
(*i)->status = TS_FINISHED; |
|
|
|
if (transfer->transfered > transfer->size) { |
|
|
|
qDebug() << "overread?"; |
|
|
|
qDebug() << "file size" << transfer->size; |
|
|
|
qDebug() << "transfered bytes" << transfer->transfered; |
|
|
|
} |
|
|
|
|
|
|
|
m_UploadDict.remove(*i); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
emit uploadUpdated(transfer); |
|
|
|
} |
|
|
|
if (!block.isEmpty()) |
|
|
|
m_Socket->write(block); |
|
|
|
break; |
|
|
|
case TS_CLOSING: |
|
|
|
header.type = HT_CLOSE; |
|
|
|
header.id = transfer->id; |
|
|
|
header.length = 0; |
|
|
|
|
|
|
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader)); |
|
|
|
|
|
|
|
transfer->status = TS_FINISHED; |
|
|
|
|
|
|
|
m_Uploads.dequeue(); |
|
|
|
emit uploadUpdated(transfer); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (!block.isEmpty()) |
|
|
|
m_Socket->write(block); |
|
|
|
} |
|
|
|
|
|
|
|
void CWorker::readHeader(QDataStream & in) { |
|
|
@ -292,7 +279,7 @@ namespace qftrans { |
|
|
|
target = m_DownloadDict[m_LastHeader.id]; |
|
|
|
} |
|
|
|
//id not in dict
|
|
|
|
else if (m_LastHeader.type == HT_ID) { |
|
|
|
else if (m_LastHeader.type == HT_ANNOUNCE) { |
|
|
|
//new file announced
|
|
|
|
qDebug() << "download announced"; |
|
|
|
TransferData * newFile = new TransferData; |
|
|
@ -302,31 +289,27 @@ namespace qftrans { |
|
|
|
newFile->localFile = false; |
|
|
|
newFile->status = TS_WAITING; |
|
|
|
newFile->fileDir = m_DestinationDir; |
|
|
|
target = newFile; |
|
|
|
} |
|
|
|
|
|
|
|
//check valid target and data available
|
|
|
|
if (target && m_LastHeader.length) { |
|
|
|
switch (m_LastHeader.type) { |
|
|
|
case HT_ID: |
|
|
|
target->status = TS_WAITING; |
|
|
|
// QFile::remove(target->fileDir + QDir::separator() + target->fileName);
|
|
|
|
emit downloadUpdated(target); |
|
|
|
break; |
|
|
|
case HT_SIZE: |
|
|
|
case HT_ANNOUNCE: |
|
|
|
qDebug() << "reading size.."; |
|
|
|
in >> target->size; |
|
|
|
qDebug() << "got size:" << target->size; |
|
|
|
break; |
|
|
|
case HT_NAME: |
|
|
|
qDebug() << "reading filename.."; |
|
|
|
in >> target->fileName; |
|
|
|
qDebug() << "got filename:" << target->fileName; |
|
|
|
emit downloadUpdated(target); |
|
|
|
qDebug() << "trying to send HT_ACK"; |
|
|
|
|
|
|
|
//TODO better do this async
|
|
|
|
sendAcknowledge(m_LastHeader.id); |
|
|
|
break; |
|
|
|
case HT_DATA: { |
|
|
|
case HT_DATA: |
|
|
|
{ |
|
|
|
// qDebug() << "got data" << target->transfered << '/' << target->size;
|
|
|
|
QFile file(target->fileDir + QDir::separator() + target->fileName); |
|
|
|
if (target->status == TS_WAITING) { |
|
|
|