Upstream tarball 10153
[amule.git] / src / Packet.cpp
blob629914c30aa0428468fb57cc7afcc96f7d7ff2a8
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 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.
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.
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
26 #include <zlib.h> // Needed for uLongf
28 #include "Packet.h" // Interface declarations
30 #include <protocol/Protocols.h>
32 #include "MemFile.h" // Needed for CMemFile
33 #include "OtherStructs.h" // Needed for Header_Struct
34 #include "ArchSpecific.h" // Needed for ENDIAN_*
36 // Copy constructor
37 CPacket::CPacket(CPacket &p)
39 size = p.size;
40 opcode = p.opcode;
41 prot = p.prot;
42 m_bSplitted = p.m_bSplitted;
43 m_bLastSplitted = p.m_bLastSplitted;
44 m_bPacked = p.m_bPacked;
45 m_bFromPF = p.m_bFromPF;
46 memcpy(head, p.head, sizeof head);
47 tempbuffer = NULL;
48 if (p.completebuffer) {
49 completebuffer = new byte[size + 10];;
50 pBuffer = completebuffer + sizeof(Header_Struct);
51 } else {
52 completebuffer = NULL;
53 if (p.pBuffer) {
54 pBuffer = new byte[size];
55 } else {
56 pBuffer = NULL;
59 if (pBuffer)
60 memcpy( pBuffer, p.pBuffer, size );
63 CPacket::CPacket(uint8 protocol)
65 size = 0;
66 opcode = 0;
67 prot = protocol;
68 m_bSplitted = false;
69 m_bLastSplitted = false;
70 m_bPacked = false;
71 m_bFromPF = false;
72 memset(head, 0, sizeof head);
73 tempbuffer = NULL;
74 completebuffer = NULL;
75 pBuffer = NULL;
78 // only used for receiving packets
79 CPacket::CPacket(byte* rawHeader, byte *buf)
81 memset(head, 0, sizeof head);
82 Header_Struct* header = (Header_Struct*)rawHeader;
83 size = ENDIAN_SWAP_32(header->packetlength) - 1;
84 opcode = header->command;
85 prot = header->eDonkeyID;
86 m_bSplitted = false;
87 m_bLastSplitted = false;
88 m_bPacked = false;
89 m_bFromPF = false;
90 tempbuffer = NULL;
91 completebuffer = NULL;
92 pBuffer = buf;
95 CPacket::CPacket(const CMemFile& datafile, uint8 protocol, uint8 ucOpcode)
97 size = datafile.GetLength();
98 opcode = ucOpcode;
99 prot = protocol;
100 m_bSplitted = false;
101 m_bLastSplitted = false;
102 m_bPacked = false;
103 m_bFromPF = false;
104 memset(head, 0, sizeof head);
105 tempbuffer = NULL;
106 completebuffer = new byte[size + sizeof(Header_Struct)/*Why this 4?*/];
107 pBuffer = completebuffer + sizeof(Header_Struct);
109 // Write contents of MemFile to buffer (while keeping original position in file)
110 off_t position = datafile.GetPosition();
111 datafile.Seek(0, wxFromStart);
112 datafile.Read(pBuffer, size);
113 datafile.Seek(position, wxFromStart);
116 CPacket::CPacket(int8 in_opcode, uint32 in_size, uint8 protocol, bool bFromPF)
118 size = in_size;
119 opcode = in_opcode;
120 prot = protocol;
121 m_bSplitted = false;
122 m_bLastSplitted = false;
123 m_bPacked = false;
124 m_bFromPF = bFromPF;
125 memset(head, 0, sizeof head);
126 tempbuffer = NULL;
127 if (in_size) {
128 completebuffer = new byte[in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/];
129 pBuffer = completebuffer + sizeof(Header_Struct);
130 memset(completebuffer, 0, in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/);
131 } else {
132 completebuffer = NULL;
133 pBuffer = NULL;
137 // only used for splitted packets!
138 CPacket::CPacket(byte* pPacketPart, uint32 nSize, bool bLast, bool bFromPF)
140 size = nSize - sizeof(Header_Struct);
141 opcode = 0;
142 prot = 0;
143 m_bSplitted = true;
144 m_bLastSplitted = bLast;
145 m_bPacked = false;
146 m_bFromPF = bFromPF;
147 memset(head, 0, sizeof head);
148 tempbuffer = NULL;
149 completebuffer = pPacketPart;
150 pBuffer = NULL;
153 CPacket::~CPacket()
155 // Never deletes pBuffer when completebuffer is not NULL
156 if (completebuffer) {
157 delete [] completebuffer;
158 } else if (pBuffer) {
159 // On the other hand, if completebuffer is NULL and pBuffer is not NULL
160 delete [] pBuffer;
163 if (tempbuffer) {
164 delete [] tempbuffer;
168 uint32 CPacket::GetPacketSizeFromHeader(const byte* rawHeader)
170 Header_Struct* header = (Header_Struct*)rawHeader;
171 uint32 size = ENDIAN_SWAP_32(header->packetlength);
172 if (size < 1 || size >= 0x7ffffff0u)
173 return 0;
174 return size - 1;
177 void CPacket::CopyToDataBuffer(unsigned int offset, const byte* data, unsigned int n)
179 wxASSERT(offset + n <= size + 1);
180 memcpy(pBuffer + offset, data, n);
183 byte* CPacket::GetPacket() {
184 if (completebuffer) {
185 if (!m_bSplitted) {
186 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct));
188 return completebuffer;
189 } else {
190 if (tempbuffer){
191 delete [] tempbuffer;
192 tempbuffer = NULL;
194 tempbuffer = new byte[size + sizeof(Header_Struct) + 4 /* why this 4?*/];
195 memcpy(tempbuffer , GetHeader(), sizeof(Header_Struct));
196 memcpy(tempbuffer + sizeof(Header_Struct), pBuffer , size);
197 return tempbuffer;
201 byte* CPacket::DetachPacket() {
202 if (completebuffer) {
203 if (!m_bSplitted) {
204 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct));
206 byte* result = completebuffer;
207 completebuffer = pBuffer = NULL;
208 return result;
209 } else{
210 if (tempbuffer){
211 delete[] tempbuffer;
212 tempbuffer = NULL;
214 tempbuffer = new byte[size+sizeof(Header_Struct)+4 /* Why this 4?*/];
215 memcpy(tempbuffer,GetHeader(),sizeof(Header_Struct));
216 memcpy(tempbuffer+sizeof(Header_Struct),pBuffer,size);
217 byte* result = tempbuffer;
218 tempbuffer = 0;
219 return result;
223 byte* CPacket::GetHeader() {
224 wxASSERT( !m_bSplitted );
226 Header_Struct* header = (Header_Struct*) head;
227 header->command = opcode;
228 header->eDonkeyID = prot;
229 header->packetlength = ENDIAN_SWAP_32(size + 1);
231 return head;
234 byte* CPacket::GetUDPHeader() {
235 wxASSERT( !m_bSplitted );
237 memset(head, 0, 6);
238 UDP_Header_Struct* header = (UDP_Header_Struct*) head;
239 header->eDonkeyID = prot;
240 header->command = opcode;
242 return head;
246 void CPacket::PackPacket()
248 wxASSERT(!m_bSplitted);
250 uLongf newsize = size + 300;
251 byte* output = new byte[newsize];
253 uint16 result = compress2(output, &newsize, pBuffer, size, Z_BEST_COMPRESSION);
255 if (result != Z_OK || size <= newsize) {
256 delete[] output;
257 return;
260 if (prot == OP_KADEMLIAHEADER) {
261 prot = OP_KADEMLIAPACKEDPROT;
262 } else {
263 prot = OP_PACKEDPROT;
266 memcpy(pBuffer, output, newsize);
267 delete[] output;
268 m_bPacked = true;
270 size = newsize;
274 bool CPacket::UnPackPacket(uint32 uMaxDecompressedSize) {
275 wxASSERT( prot == OP_PACKEDPROT );
277 uint32 nNewSize = size * 10 + 300;
279 if (nNewSize > uMaxDecompressedSize){
280 nNewSize = uMaxDecompressedSize;
283 byte* unpack = new byte[nNewSize];
284 uLongf unpackedsize = nNewSize;
285 uint16 result = uncompress(unpack, &unpackedsize, pBuffer, size);
287 if (result == Z_OK) {
288 wxASSERT( completebuffer == NULL );
289 wxASSERT( pBuffer != NULL );
291 size = unpackedsize;
292 delete[] pBuffer;
293 pBuffer = unpack;
294 prot = OP_EMULEPROT;
295 return true;
298 delete[] unpack;
299 return false;
303 void CPacket::Copy16ToDataBuffer(const void* data)
305 md4cpy(pBuffer, data);
309 void CPacket::CopyUInt32ToDataBuffer(uint32 data, unsigned int offset)
311 wxCHECK_RET(offset <= size - sizeof(uint32), wxT("Bad offset in CopyUInt32ToDataBuffer."));
312 PokeUInt32( pBuffer + offset, data );
314 // File_checked_for_headers