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.

csendthread.cpp 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /***************************************************************************
  2. * Copyright (C) 2008 by Oliver Groß *
  3. * z.o.gross@gmx.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include "csenderthread.h"
  21. #include <QTcpSocket>
  22. #include <QByteArray>
  23. #include <QDataStream>
  24. #include <QFile>
  25. namespace qftrans {
  26. CSenderThread::CSenderThread(QTcpSocket * socket, QObject * parent) : QThread(parent), m_Socket(socket), m_IdCounter(0) {
  27. }
  28. CSenderThread::~CSenderThread() {
  29. }
  30. void CSenderThread::addUpload(TransferData * upload) {
  31. if (!m_DataDict.contains(upload)) {
  32. qDebug() << "adding upload";
  33. m_DataDict.insert(upload, m_IdCounter);
  34. m_IdCounter++;
  35. }
  36. }
  37. void CSenderThread::removeUpload(TransferData * transfer) {
  38. transfer->status = TS_CLOSING;
  39. if (m_Socket->bytesToWrite() == 0) {
  40. qDebug() << "executing upload";
  41. writeData();
  42. }
  43. }
  44. void CSenderThread::startUpload(TransferData * upload) {
  45. if (m_DataDict.contains(upload) && upload->status == TS_WAITING) {
  46. qDebug() << "scheduling upload for announce";
  47. upload->status = TS_ANNOUNCING;
  48. if (m_Socket->bytesToWrite() == 0) {
  49. qDebug() << "executing upload";
  50. writeData();
  51. }
  52. }
  53. }
  54. void CSenderThread::startUploadData(quint32 id) {
  55. TransferData * transfer = m_DataDict.key(id);
  56. if (transfer) {
  57. qDebug() << "scheduling upload for transfer";
  58. transfer->status = TS_TRANSFERING;
  59. if (m_Socket->bytesToWrite() == 0) {
  60. qDebug() << "executing upload";
  61. writeData();
  62. }
  63. }
  64. }
  65. void CSenderThread::sendAcknowledge(quint32 id) {
  66. QByteArray block;
  67. QDataStream out(&block, QIODevice::WriteOnly);
  68. out.setVersion(QDataStream::Qt_4_0);
  69. TransferHeader header;
  70. // header.descriptor = DESCRIPTOR_STRING;
  71. header.type = HT_ACK;
  72. header.id = id;
  73. header.length = 0;
  74. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  75. qDebug() << "sending HT_ACK" << id;
  76. m_Socket->write(block);
  77. }
  78. void CSendThread::writeData() {
  79. if (m_DataDict.isEmpty())
  80. exit();
  81. QByteArray block;
  82. QDataStream out(&block, QIODevice::ReadWrite);
  83. out.setVersion(QDataStream::Qt_4_0);
  84. QTransferDataList transfers = m_DataDict.keys();
  85. QTransferDataList::iterator i;
  86. for (i = transfers.begin(); i != transfers.end(); ++i) {
  87. block.clear();
  88. TransferHeader header;
  89. // header.descriptor = DESCRIPTOR_STRING;
  90. switch ((*i)->status) {
  91. case TS_ANNOUNCING: {
  92. qDebug() << "announcing" << m_DataDict[*i];
  93. if ((*i)->transfered)
  94. (*i)->transfered = 0;
  95. // ID header with no data
  96. header.type = HT_ID;
  97. header.id = m_DataDict[*i];
  98. header.length = 0;
  99. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  100. //size header with size
  101. header.type = HT_SIZE;
  102. header.length = sizeof(qint64);
  103. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  104. qDebug() << "sending size" << (*i)->size;
  105. out << (*i)->size;
  106. //name header with file name
  107. qint64 oldPosition = block.size();
  108. //fake write filename
  109. out << (*i)->fileName;
  110. out.device()->seek(oldPosition);
  111. header.type = HT_NAME;
  112. header.length = quint32(block.size() - oldPosition);
  113. // qDebug() << "pos" << out.device()->pos() << block.size();
  114. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  115. // qDebug() << "pos post header" << out.device()->pos() << block.size();
  116. // qint64 oldPosition = block.size() - sizeof(quint32);
  117. qDebug() << "sending filename" << (*i)->fileName;
  118. out << (*i)->fileName;
  119. // qDebug() << "pos post filename" << out.device()->pos() << block.size();
  120. // out.device()->seek(oldPosition);
  121. // qDebug() << "pos post seek" << out.device()->pos();
  122. /* qDebug() << "filename data length" << header.length;
  123. out << header.length;
  124. out.device()->seek(oldPosition);
  125. out >> header.length;
  126. qDebug() << "written length" << header.length;
  127. out.device()->seek(block.size());
  128. qDebug() << "pos post length correct" << out.device()->pos() << block.size();*/
  129. (*i)->status = TS_WAITING;
  130. }
  131. break;
  132. case TS_TRANSFERING: {
  133. // qDebug() << "transfering" << m_DataDict[*i];
  134. header.type = HT_DATA;
  135. header.id = m_DataDict[*i];
  136. if ((*i)->transfered + DATA_BLOCK_SIZE < (*i)->size)
  137. header.length = DATA_BLOCK_SIZE;
  138. else
  139. header.length = (*i)->size - (*i)->transfered;
  140. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  141. char * buffer = new char[header.length];
  142. QFile file((*i)->fileDir + (*i)->fileName);
  143. file.open(QIODevice::ReadOnly);
  144. QDataStream in(&file);
  145. in.readRawData(buffer, header.length);
  146. out.writeRawData((const char *)(buffer), header.length);
  147. (*i)->transfered += header.length;
  148. delete[] buffer;
  149. if ((*i)->transfered >= (*i)->size)
  150. (*i)->status = TS_CLOSING;
  151. emit uploadUpdated(*i);
  152. }
  153. break;
  154. case TS_CLOSING:
  155. header.type = HT_CLOSE;
  156. header.id = m_DataDict[*i];
  157. header.length = 0;
  158. out.writeRawData((const char *)(&header), sizeof(TransferHeader));
  159. (*i)->status = TS_FINISHED;
  160. m_DataDict.remove(*i);
  161. break;
  162. default:
  163. break;
  164. }
  165. if (!block.isEmpty())
  166. m_Socket->write(block);
  167. }
  168. }
  169. void CSendThread::run() {
  170. qDebug() << "start sender thread";
  171. connect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData()));
  172. exec();
  173. disconnect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData()));
  174. }
  175. }