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
CPacket(CPacket & p)38 CPacket::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 
CPacket(uint8 protocol)64 CPacket::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
CPacket(byte * rawHeader,byte * buf)80 CPacket::CPacket(byte* rawHeader, byte *buf)
81 {
82 	memset(head, 0, sizeof head);
83 	Header_Struct* header = reinterpret_cast<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 
CPacket(const CMemFile & datafile,uint8 protocol,uint8 ucOpcode)96 CPacket::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 
CPacket(int8 in_opcode,uint32 in_size,uint8 protocol,bool bFromPF)117 CPacket::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!
CPacket(byte * pPacketPart,uint32 nSize,bool bLast,bool bFromPF)139 CPacket::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 
~CPacket()154 CPacket::~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 
GetPacketSizeFromHeader(const byte * rawHeader)169 uint32 CPacket::GetPacketSizeFromHeader(const byte* rawHeader)
170 {
171 	const Header_Struct* header = reinterpret_cast<const 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 
CopyToDataBuffer(unsigned int offset,const byte * data,unsigned int n)178 void 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 
GetPacket()184 byte* 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 
DetachPacket()202 byte* 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 
GetHeader()224 byte* CPacket::GetHeader() {
225 	wxASSERT( !m_bSplitted );
226 
227 	Header_Struct* header = reinterpret_cast<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 
GetUDPHeader()235 byte* CPacket::GetUDPHeader() {
236 	wxASSERT( !m_bSplitted );
237 
238 	memset(head, 0, 6);
239 	UDP_Header_Struct* header = reinterpret_cast<UDP_Header_Struct*>(head);
240 	header->eDonkeyID =  prot;
241 	header->command = opcode;
242 
243 	return head;
244 }
245 
246 
PackPacket()247 void 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 
UnPackPacket(uint32 uMaxDecompressedSize)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."));
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 
Copy16ToDataBuffer(const void * data)310 void CPacket::Copy16ToDataBuffer(const void* data)
311 {
312 	md4cpy(pBuffer, data);
313 }
314 
315 
CopyUInt32ToDataBuffer(uint32 data,unsigned int offset)316 void 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