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.
ktorrent/libktorrent/torrent/packet.cpp

176 lines
5.1 KiB

/***************************************************************************
* Copyright (C) 2005 by Joris Guisson *
* joris.guisson@gmail.com *
* *
* 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. *
***************************************************************************/
#include <tqstring.h>
#include <string.h>
#include <util/log.h>
#include <util/bitset.h>
#include <util/functions.h>
#include <torrent/globals.h>
#include "packet.h"
#include "request.h"
#include "chunk.h"
#include "peer.h"
namespace bt
{
static Uint8* AllocPacket(Uint32 size,Uint8 type)
{
Uint8* data = new Uint8[size];
WriteUint32(data,0,size - 4);
data[4] = type;
return data;
}
Packet::Packet(Uint8 type) : data(0),size(0),written(0)
{
size = 5;
data = AllocPacket(size,type);
}
Packet::Packet(Uint16 port) : data(0),size(0),written(0)
{
size = 7;
data = AllocPacket(size,PORT);
WriteUint16(data,5,port);
}
Packet::Packet(Uint32 chunk,Uint8 type) : data(0),size(0),written(0)
{
size = 9;
data = AllocPacket(size,type);
WriteUint32(data,5,chunk);
}
Packet::Packet(const BitSet & bs) : data(0),size(0),written(0)
{
size = 5 + bs.getNumBytes();
data = AllocPacket(size,BITFIELD);
memcpy(data+5,bs.getData(),bs.getNumBytes());
}
Packet::Packet(const Request & r,Uint8 type) : data(0),size(0),written(0)
{
size = 17;
data = AllocPacket(size,type);
WriteUint32(data,5,r.getIndex());
WriteUint32(data,9,r.getOffset());
WriteUint32(data,13,r.getLength());
}
Packet::Packet(Uint32 index,Uint32 begin,Uint32 len,Chunk* ch) : data(0),size(0),written(0)
{
size = 13 + len;
data = AllocPacket(size,PIECE);
WriteUint32(data,5,index);
WriteUint32(data,9,begin);
memcpy(data+13,ch->getData() + begin,len);
}
Packet::Packet(Uint8 ext_id,const TQByteArray & ext_data) : data(0),size(0),written(0)
{
size = 6 + ext_data.size();
data = AllocPacket(size,EXTENDED);
data[5] = ext_id;
memcpy(data + 6,ext_data.data(),ext_data.size());
}
Packet::~Packet()
{
delete [] data;
}
bool Packet::isPiece(const Request & req) const
{
if (data[4] == PIECE)
{
if (ReadUint32(data,5) != req.getIndex())
return false;
if (ReadUint32(data,9) != req.getOffset())
return false;
if (ReadUint32(data,13) != req.getLength())
return false;
return true;
}
return false;
}
Packet* Packet::makeRejectOfPiece()
{
if (getType() != PIECE)
return 0;
Uint32 idx = bt::ReadUint32(data,5);
Uint32 off = bt::ReadUint32(data,9);
Uint32 len = size - 13;
// Out(SYS_CON|LOG_DEBUG) << "Packet::makeRejectOfPiece " << idx << " " << off << " " << len << endl;
return new Packet(Request(idx,off,len,0),bt::REJECT_REQUEST);
}
/*
TQString Packet::debugString() const
{
if (!data)
return TQString();
switch (data[4])
{
case CHOKE : return TQString("CHOKE %1 %2").arg(hdr_length).arg(data_length);
case UNCHOKE : return TQString("UNCHOKE %1 %2").arg(hdr_length).arg(data_length);
case INTERESTED : return TQString("INTERESTED %1 %2").arg(hdr_length).arg(data_length);
case NOT_INTERESTED : return TQString("NOT_INTERESTED %1 %2").arg(hdr_length).arg(data_length);
case HAVE : return TQString("HAVE %1 %2").arg(hdr_length).arg(data_length);
case BITFIELD : return TQString("BITFIELD %1 %2").arg(hdr_length).arg(data_length);
case PIECE : return TQString("PIECE %1 %2").arg(hdr_length).arg(data_length);
case REQUEST : return TQString("REQUEST %1 %2").arg(hdr_length).arg(data_length);
case CANCEL : return TQString("CANCEL %1 %2").arg(hdr_length).arg(data_length);
default: return TQString("UNKNOWN %1 %2").arg(hdr_length).arg(data_length);
}
}
*/
bool Packet::isOK() const
{
if (!data)
return false;
return true;
}
Uint32 Packet::putInOutputBuffer(Uint8* buf,Uint32 max_to_put,bool & piece)
{
piece = data[4] == PIECE;
Uint32 bw = size - written;
if (!bw) // nothing to write
return 0;
if (bw > max_to_put)
bw = max_to_put;
memcpy(buf,data + written,bw);
written += bw;
return bw;
}
}