2 // This file is part of the aMule Project.
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 )
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 "MemFile.h" // Needed for CMemFile
33 #include "OtherStructs.h" // Needed for Header_Struct
34 #include "ArchSpecific.h" // Needed for ENDIAN_*
37 CPacket::CPacket(CPacket
&p
)
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
);
48 if (p
.completebuffer
) {
49 completebuffer
= new byte
[size
+ 10];;
50 pBuffer
= completebuffer
+ sizeof(Header_Struct
);
52 completebuffer
= NULL
;
54 pBuffer
= new byte
[size
];
60 memcpy( pBuffer
, p
.pBuffer
, size
);
63 CPacket::CPacket(uint8 protocol
)
69 m_bLastSplitted
= false;
72 memset(head
, 0, sizeof head
);
74 completebuffer
= 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
;
87 m_bLastSplitted
= false;
91 completebuffer
= NULL
;
95 CPacket::CPacket(const CMemFile
& datafile
, uint8 protocol
, uint8 ucOpcode
)
97 size
= datafile
.GetLength();
101 m_bLastSplitted
= false;
104 memset(head
, 0, sizeof head
);
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
)
122 m_bLastSplitted
= false;
125 memset(head
, 0, sizeof head
);
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?*/);
132 completebuffer
= NULL
;
137 // only used for splitted packets!
138 CPacket::CPacket(byte
* pPacketPart
, uint32 nSize
, bool bLast
, bool bFromPF
)
140 size
= nSize
- sizeof(Header_Struct
);
144 m_bLastSplitted
= bLast
;
147 memset(head
, 0, sizeof head
);
149 completebuffer
= pPacketPart
;
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
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
)
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
) {
186 memcpy(completebuffer
, GetHeader(), sizeof(Header_Struct
));
188 return completebuffer
;
191 delete [] tempbuffer
;
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
);
201 byte
* CPacket::DetachPacket() {
202 if (completebuffer
) {
204 memcpy(completebuffer
, GetHeader(), sizeof(Header_Struct
));
206 byte
* result
= completebuffer
;
207 completebuffer
= pBuffer
= 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
;
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);
234 byte
* CPacket::GetUDPHeader() {
235 wxASSERT( !m_bSplitted
);
238 UDP_Header_Struct
* header
= (UDP_Header_Struct
*) head
;
239 header
->eDonkeyID
= prot
;
240 header
->command
= opcode
;
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
) {
260 if (prot
== OP_KADEMLIAHEADER
) {
261 prot
= OP_KADEMLIAPACKEDPROT
;
263 prot
= OP_PACKEDPROT
;
266 memcpy(pBuffer
, output
, 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
);
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