2 // This file is part of the aMule Project.
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 )
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
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.
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 "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_*
38 CPacket::CPacket(CPacket
&p
)
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
);
49 if (p
.completebuffer
) {
50 completebuffer
= new byte
[size
+ 10];;
51 pBuffer
= completebuffer
+ sizeof(Header_Struct
);
53 completebuffer
= NULL
;
55 pBuffer
= new byte
[size
];
61 memcpy( pBuffer
, p
.pBuffer
, size
);
64 CPacket::CPacket(uint8 protocol
)
70 m_bLastSplitted
= false;
73 memset(head
, 0, sizeof head
);
75 completebuffer
= NULL
;
79 // only used for receiving packets
80 CPacket::CPacket(byte
* rawHeader
, byte
*buf
)
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
;
88 m_bLastSplitted
= false;
92 completebuffer
= NULL
;
96 CPacket::CPacket(const CMemFile
& datafile
, uint8 protocol
, uint8 ucOpcode
)
98 size
= datafile
.GetLength();
102 m_bLastSplitted
= false;
105 memset(head
, 0, sizeof head
);
107 completebuffer
= new byte
[size
+ sizeof(Header_Struct
)/*Why this 4?*/];
108 pBuffer
= completebuffer
+ sizeof(Header_Struct
);
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
);
117 CPacket::CPacket(int8 in_opcode
, uint32 in_size
, uint8 protocol
, bool bFromPF
)
123 m_bLastSplitted
= false;
126 memset(head
, 0, sizeof head
);
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?*/);
133 completebuffer
= NULL
;
138 // only used for splitted packets!
139 CPacket::CPacket(byte
* pPacketPart
, uint32 nSize
, bool bLast
, bool bFromPF
)
141 size
= nSize
- sizeof(Header_Struct
);
145 m_bLastSplitted
= bLast
;
148 memset(head
, 0, sizeof head
);
150 completebuffer
= pPacketPart
;
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
165 delete [] tempbuffer
;
169 uint32
CPacket::GetPacketSizeFromHeader(const byte
* rawHeader
)
171 Header_Struct
* header
= (Header_Struct
*)rawHeader
;
172 uint32 size
= ENDIAN_SWAP_32(header
->packetlength
);
173 if (size
< 1 || size
>= 0x7ffffff0u
)
178 void CPacket::CopyToDataBuffer(unsigned int offset
, const byte
* data
, unsigned int n
)
180 wxASSERT(offset
+ n
<= size
+ 1);
181 memcpy(pBuffer
+ offset
, data
, n
);
184 byte
* CPacket::GetPacket() {
185 if (completebuffer
) {
187 memcpy(completebuffer
, GetHeader(), sizeof(Header_Struct
));
189 return completebuffer
;
192 delete [] tempbuffer
;
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
);
202 byte
* CPacket::DetachPacket() {
203 if (completebuffer
) {
205 memcpy(completebuffer
, GetHeader(), sizeof(Header_Struct
));
207 byte
* result
= completebuffer
;
208 completebuffer
= pBuffer
= NULL
;
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
;
224 byte
* CPacket::GetHeader() {
225 wxASSERT( !m_bSplitted
);
227 Header_Struct
* header
= (Header_Struct
*) head
;
228 header
->command
= opcode
;
229 header
->eDonkeyID
= prot
;
230 header
->packetlength
= ENDIAN_SWAP_32(size
+ 1);
235 byte
* CPacket::GetUDPHeader() {
236 wxASSERT( !m_bSplitted
);
239 UDP_Header_Struct
* header
= (UDP_Header_Struct
*) head
;
240 header
->eDonkeyID
= prot
;
241 header
->command
= opcode
;
247 void CPacket::PackPacket()
249 wxASSERT(!m_bSplitted
);
251 uLongf newsize
= size
+ 300;
252 byte
* output
= new byte
[newsize
];
254 uint16 result
= compress2(output
, &newsize
, pBuffer
, size
, Z_BEST_COMPRESSION
);
256 if (result
!= Z_OK
|| size
<= newsize
) {
261 if (prot
== OP_KADEMLIAHEADER
) {
262 prot
= OP_KADEMLIAPACKEDPROT
;
264 prot
= OP_PACKEDPROT
;
267 memcpy(pBuffer
, output
, newsize
);
275 bool 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."));
284 uint32 nNewSize
= size
* 10 + 300;
286 if (nNewSize
> uMaxDecompressedSize
){
287 nNewSize
= uMaxDecompressedSize
;
290 byte
* unpack
= new byte
[nNewSize
];
291 uLongf unpackedsize
= nNewSize
;
292 uint16 result
= uncompress(unpack
, &unpackedsize
, pBuffer
, size
);
294 if (result
== Z_OK
) {
295 wxASSERT( completebuffer
== NULL
);
296 wxASSERT( pBuffer
!= NULL
);
310 void CPacket::Copy16ToDataBuffer(const void* data
)
312 md4cpy(pBuffer
, data
);
316 void CPacket::CopyUInt32ToDataBuffer(uint32 data
, unsigned int offset
)
318 wxCHECK_RET(offset
<= size
- sizeof(uint32
), wxT("Bad offset in CopyUInt32ToDataBuffer."));
319 PokeUInt32( pBuffer
+ offset
, data
);
321 // File_checked_for_headers