summaryrefslogtreecommitdiffstats
path: root/libktorrent/torrent/packetreader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libktorrent/torrent/packetreader.cpp')
-rw-r--r--libktorrent/torrent/packetreader.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/libktorrent/torrent/packetreader.cpp b/libktorrent/torrent/packetreader.cpp
new file mode 100644
index 0000000..8df348b
--- /dev/null
+++ b/libktorrent/torrent/packetreader.cpp
@@ -0,0 +1,247 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Joris Guisson *
+ * *
+ * 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., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+//#define LOG_PACKET
+#ifdef LOG_PACKET
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <util/log.h>
+#include <util/file.h>
+#include <util/functions.h>
+#include "packetreader.h"
+#include "peer.h"
+
+
+namespace bt
+{
+#ifdef LOG_PACKET
+ static void LogPacket(const Uint8* data,Uint32 size,Uint32 len)
+ {
+ QString file = QString("/tmp/kt-packetreader-%1.log").arg(getpid());
+ File fptr;
+ if (!fptr.open(file,"a"))
+ return;
+
+
+ QString tmp = QString("PACKET len = %1, type = %2\nDATA: \n").arg(len).arg(data[0]);
+
+ fptr.write(tmp.ascii(),tmp.length());
+
+ Uint32 j = 0;
+ if (size <= 40)
+ {
+ for (Uint32 i = 0;i < size;i++)
+ {
+ tmp = QString("0x%1 ").arg(data[i],0,16);
+ fptr.write(tmp.ascii(),tmp.length());
+ j++;
+ if (j > 10)
+ {
+ fptr.write("\n",1);
+ j = 0;
+ }
+ }
+ }
+ else
+ {
+ for (Uint32 i = 0;i < 20;i++)
+ {
+ tmp = QString("0x%1 ").arg(data[i],0,16);
+ fptr.write(tmp.ascii(),tmp.length());
+ j++;
+ if (j > 10)
+ {
+ fptr.write("\n",1);
+ j = 0;
+ }
+ }
+ tmp = QString("\n ... \n");
+ fptr.write(tmp.ascii(),tmp.length());
+ for (Uint32 i = size - 20;i < size;i++)
+ {
+ tmp = QString("0x%1 ").arg(data[i],0,16);
+ fptr.write(tmp.ascii(),tmp.length());
+ j++;
+ if (j > 10)
+ {
+ fptr.write("\n",1);
+ j = 0;
+ }
+ }
+ }
+ fptr.write("\n",1);
+ }
+#endif
+
+ IncomingPacket::IncomingPacket(Uint32 size) : data(0),size(size),read(0)
+ {
+ data = new Uint8[size];
+ }
+
+ IncomingPacket::~IncomingPacket()
+ {
+ delete [] data;
+ }
+
+ PacketReader::PacketReader(Peer* peer)
+ : peer(peer),error(false)
+ {
+ packet_queue.setAutoDelete(true);
+ len_received = -1;
+ }
+
+
+ PacketReader::~PacketReader()
+ {
+ }
+
+
+ void PacketReader::update()
+ {
+ if (error)
+ return;
+
+ mutex.lock();
+ // pass packets to peer
+ while (packet_queue.count() > 0)
+ {
+ IncomingPacket* pck = packet_queue.first();
+ if (pck->read == pck->size)
+ {
+ // full packet is read pass it to peer
+ peer->packetReady(pck->data,pck->size);
+ packet_queue.removeFirst();
+ }
+ else
+ {
+ // packet is not yet full, break out of loop
+ break;
+ }
+ }
+ mutex.unlock();
+ }
+
+ Uint32 PacketReader::newPacket(Uint8* buf,Uint32 size)
+ {
+ Uint32 packet_length = 0;
+ Uint32 am_of_len_read = 0;
+ if (len_received > 0)
+ {
+ if (size < 4 - len_received)
+ {
+ memcpy(len + len_received,buf,size);
+ len_received += size;
+ return size;
+ }
+ else
+ {
+ memcpy(len + len_received,buf,4 - len_received);
+ am_of_len_read = 4 - len_received;
+ len_received = 0;
+ packet_length = ReadUint32(len,0);
+
+ }
+ }
+ else if (size < 4)
+ {
+ memcpy(len,buf,size);
+ len_received = size;
+ return size;
+ }
+ else
+ {
+ packet_length = ReadUint32(buf,0);
+ am_of_len_read = 4;
+ }
+
+ if (packet_length == 0)
+ return am_of_len_read;
+
+ if (packet_length > MAX_PIECE_LEN + 13)
+ {
+ Out(SYS_CON|LOG_DEBUG) << " packet_length too large " << packet_length << endl;
+
+ error = true;
+ return size;
+ }
+
+ IncomingPacket* pck = new IncomingPacket(packet_length);
+ packet_queue.append(pck);
+ return am_of_len_read + readPacket(buf + am_of_len_read,size - am_of_len_read);
+ }
+
+ Uint32 PacketReader::readPacket(Uint8* buf,Uint32 size)
+ {
+ if (!size)
+ return 0;
+
+ IncomingPacket* pck = packet_queue.last();
+ if (pck->read + size >= pck->size)
+ {
+ // we can read the full packet
+ Uint32 tr = pck->size - pck->read;
+ memcpy(pck->data + pck->read,buf,tr);
+ pck->read += tr;
+ return tr;
+ }
+ else
+ {
+ // we can do a partial read
+ Uint32 tr = size;
+ memcpy(pck->data + pck->read,buf,tr);
+ pck->read += tr;
+ return tr;
+ }
+ }
+
+
+ void PacketReader::onDataReady(Uint8* buf,Uint32 size)
+ {
+ if (error)
+ return;
+
+ mutex.lock();
+ if (packet_queue.count() == 0)
+ {
+ Uint32 ret = 0;
+ while (ret < size && !error)
+ {
+ ret += newPacket(buf + ret,size - ret);
+ }
+ }
+ else
+ {
+ Uint32 ret = 0;
+ IncomingPacket* pck = packet_queue.last();
+ if (pck->read == pck->size) // last packet in queue is fully read
+ ret = newPacket(buf,size);
+ else
+ ret = readPacket(buf,size);
+
+ while (ret < size && !error)
+ {
+ ret += newPacket(buf + ret,size - ret);
+ }
+ }
+ mutex.unlock();
+ }
+}