/*************************************************************************** * 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 #include #include #include #include #include #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; } }