1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26#include <zlib.h> // Needed for uLongf 27 28#include "Packet.h" // Interface declarations 29 30#include <protocol/Protocols.h> 31 32#include "Logger.h" // Neeed for AddDebugLogLineN 33#include "MemFile.h" // Needed for CMemFile 34#include "OtherStructs.h" // Needed for Header_Struct 35#include "ArchSpecific.h" // Needed for ENDIAN_* 36 37// Copy constructor 38CPacket::CPacket(CPacket &p) 39{ 40 size = p.size; 41 opcode = p.opcode; 42 prot = p.prot; 43 m_bSplitted = p.m_bSplitted; 44 m_bLastSplitted = p.m_bLastSplitted; 45 m_bPacked = p.m_bPacked; 46 m_bFromPF = p.m_bFromPF; 47 memcpy(head, p.head, sizeof head); 48 tempbuffer = NULL; 49 if (p.completebuffer) { 50 completebuffer = new byte[size + 10];; 51 pBuffer = completebuffer + sizeof(Header_Struct); 52 } else { 53 completebuffer = NULL; 54 if (p.pBuffer) { 55 pBuffer = new byte[size]; 56 } else { 57 pBuffer = NULL; 58 } 59 } 60 if (pBuffer) 61 memcpy( pBuffer, p.pBuffer, size ); 62} 63 64CPacket::CPacket(uint8 protocol) 65{ 66 size = 0; 67 opcode = 0; 68 prot = protocol; 69 m_bSplitted = false; 70 m_bLastSplitted = false; 71 m_bPacked = false; 72 m_bFromPF = false; 73 memset(head, 0, sizeof head); 74 tempbuffer = NULL; 75 completebuffer = NULL; 76 pBuffer = NULL; 77} 78 79// only used for receiving packets 80CPacket::CPacket(byte* rawHeader, byte *buf) 81{ 82 memset(head, 0, sizeof head); 83 Header_Struct* header = (Header_Struct*)rawHeader; 84 size = ENDIAN_SWAP_32(header->packetlength) - 1; 85 opcode = header->command; 86 prot = header->eDonkeyID; 87 m_bSplitted = false; 88 m_bLastSplitted = false; 89 m_bPacked = false; 90 m_bFromPF = false; 91 tempbuffer = NULL; 92 completebuffer = NULL; 93 pBuffer = buf; 94} 95 96CPacket::CPacket(const CMemFile& datafile, uint8 protocol, uint8 ucOpcode) 97{ 98 size = datafile.GetLength(); 99 opcode = ucOpcode; 100 prot = protocol; 101 m_bSplitted = false; 102 m_bLastSplitted = false; 103 m_bPacked = false; 104 m_bFromPF = false; 105 memset(head, 0, sizeof head); 106 tempbuffer = NULL; 107 completebuffer = new byte[size + sizeof(Header_Struct)/*Why this 4?*/]; 108 pBuffer = completebuffer + sizeof(Header_Struct); 109 110 // Write contents of MemFile to buffer (while keeping original position in file) 111 off_t position = datafile.GetPosition(); 112 datafile.Seek(0, wxFromStart); 113 datafile.Read(pBuffer, size); 114 datafile.Seek(position, wxFromStart); 115} 116 117CPacket::CPacket(int8 in_opcode, uint32 in_size, uint8 protocol, bool bFromPF) 118{ 119 size = in_size; 120 opcode = in_opcode; 121 prot = protocol; 122 m_bSplitted = false; 123 m_bLastSplitted = false; 124 m_bPacked = false; 125 m_bFromPF = bFromPF; 126 memset(head, 0, sizeof head); 127 tempbuffer = NULL; 128 if (in_size) { 129 completebuffer = new byte[in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/]; 130 pBuffer = completebuffer + sizeof(Header_Struct); 131 memset(completebuffer, 0, in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/); 132 } else { 133 completebuffer = NULL; 134 pBuffer = NULL; 135 } 136} 137 138// only used for splitted packets! 139CPacket::CPacket(byte* pPacketPart, uint32 nSize, bool bLast, bool bFromPF) 140{ 141 size = nSize - sizeof(Header_Struct); 142 opcode = 0; 143 prot = 0; 144 m_bSplitted = true; 145 m_bLastSplitted = bLast; 146 m_bPacked = false; 147 m_bFromPF = bFromPF; 148 memset(head, 0, sizeof head); 149 tempbuffer = NULL; 150 completebuffer = pPacketPart; 151 pBuffer = NULL; 152} 153 154CPacket::~CPacket() 155{ 156 // Never deletes pBuffer when completebuffer is not NULL 157 if (completebuffer) { 158 delete [] completebuffer; 159 } else if (pBuffer) { 160 // On the other hand, if completebuffer is NULL and pBuffer is not NULL 161 delete [] pBuffer; 162 } 163 164 if (tempbuffer) { 165 delete [] tempbuffer; 166 } 167} 168 169uint32 CPacket::GetPacketSizeFromHeader(const byte* rawHeader) 170{ 171 Header_Struct* header = (Header_Struct*)rawHeader; 172 uint32 size = ENDIAN_SWAP_32(header->packetlength); 173 if (size < 1 || size >= 0x7ffffff0u) 174 return 0; 175 return size - 1; 176} 177 178void CPacket::CopyToDataBuffer(unsigned int offset, const byte* data, unsigned int n) 179{ 180 wxASSERT(offset + n <= size + 1); 181 memcpy(pBuffer + offset, data, n); 182} 183 184byte* CPacket::GetPacket() { 185 if (completebuffer) { 186 if (!m_bSplitted) { 187 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct)); 188 } 189 return completebuffer; 190 } else { 191 if (tempbuffer){ 192 delete [] tempbuffer; 193 tempbuffer = NULL; 194 } 195 tempbuffer = new byte[size + sizeof(Header_Struct) + 4 /* why this 4?*/]; 196 memcpy(tempbuffer , GetHeader(), sizeof(Header_Struct)); 197 memcpy(tempbuffer + sizeof(Header_Struct), pBuffer , size); 198 return tempbuffer; 199 } 200} 201 202byte* CPacket::DetachPacket() { 203 if (completebuffer) { 204 if (!m_bSplitted) { 205 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct)); 206 } 207 byte* result = completebuffer; 208 completebuffer = pBuffer = NULL; 209 return result; 210 } else{ 211 if (tempbuffer){ 212 delete[] tempbuffer; 213 tempbuffer = NULL; 214 } 215 tempbuffer = new byte[size+sizeof(Header_Struct)+4 /* Why this 4?*/]; 216 memcpy(tempbuffer,GetHeader(),sizeof(Header_Struct)); 217 memcpy(tempbuffer+sizeof(Header_Struct),pBuffer,size); 218 byte* result = tempbuffer; 219 tempbuffer = 0; 220 return result; 221 } 222} 223 224byte* CPacket::GetHeader() { 225 wxASSERT( !m_bSplitted ); 226 227 Header_Struct* header = (Header_Struct*) head; 228 header->command = opcode; 229 header->eDonkeyID = prot; 230 header->packetlength = ENDIAN_SWAP_32(size + 1); 231 232 return head; 233} 234 235byte* CPacket::GetUDPHeader() { 236 wxASSERT( !m_bSplitted ); 237 238 memset(head, 0, 6); 239 UDP_Header_Struct* header = (UDP_Header_Struct*) head; 240 header->eDonkeyID = prot; 241 header->command = opcode; 242 243 return head; 244} 245 246 247void CPacket::PackPacket() 248{ 249 wxASSERT(!m_bSplitted); 250 251 uLongf newsize = size + 300; 252 byte* output = new byte[newsize]; 253 254 uint16 result = compress2(output, &newsize, pBuffer, size, Z_BEST_COMPRESSION); 255 256 if (result != Z_OK || size <= newsize) { 257 delete[] output; 258 return; 259 } 260 261 if (prot == OP_KADEMLIAHEADER) { 262 prot = OP_KADEMLIAPACKEDPROT; 263 } else { 264 prot = OP_PACKEDPROT; 265 } 266 267 memcpy(pBuffer, output, newsize); 268 delete[] output; 269 m_bPacked = true; 270 271 size = newsize; 272} 273 274 275bool CPacket::UnPackPacket(uint32 uMaxDecompressedSize) { 276 wxASSERT( prot == OP_PACKEDPROT || prot == OP_ED2KV2PACKEDPROT); 277 // OP_ED2KV2PACKEDPROT is experimental aMule test code, 278 // this should not happen yet. Leave a warining in the log. 279 if (prot == OP_ED2KV2PACKEDPROT) { 280 AddDebugLogLineN(logPacketErrors, 281 wxT("Received OP_ED2KV2PACKEDPROT.")); 282 } 283 284 uint32 nNewSize = size * 10 + 300; 285 286 if (nNewSize > uMaxDecompressedSize){ 287 nNewSize = uMaxDecompressedSize; 288 } 289 290 byte* unpack = new byte[nNewSize]; 291 uLongf unpackedsize = nNewSize; 292 uint16 result = uncompress(unpack, &unpackedsize, pBuffer, size); 293 294 if (result == Z_OK) { 295 wxASSERT( completebuffer == NULL ); 296 wxASSERT( pBuffer != NULL ); 297 298 size = unpackedsize; 299 delete[] pBuffer; 300 pBuffer = unpack; 301 prot = OP_EMULEPROT; 302 return true; 303 } 304 305 delete[] unpack; 306 return false; 307} 308 309 310void CPacket::Copy16ToDataBuffer(const void* data) 311{ 312 md4cpy(pBuffer, data); 313} 314 315 316void CPacket::CopyUInt32ToDataBuffer(uint32 data, unsigned int offset) 317{ 318 wxCHECK_RET(offset <= size - sizeof(uint32), wxT("Bad offset in CopyUInt32ToDataBuffer.")); 319 PokeUInt32( pBuffer + offset, data ); 320} 321// File_checked_for_headers 322