1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 //   work by JasonB
6 //   code under LGPL
7 //   enhanced by Dark Charlie and Albert Zeyer
8 //
9 //
10 /////////////////////////////////////////
11 
12 
13 // Network Channel class
14 // Created 16/6/01
15 // Jason Boettcher
16 
17 
18 #include <map>
19 
20 #include "LieroX.h"
21 #include "Debug.h"
22 #include "CChannel.h"
23 #include "StringUtils.h"
24 #include "Timer.h"
25 #include "MathLib.h"
26 
27 
28 
29 // default max size for UDP packets for windows is 1280
30 // only a size of 512 is guaranteed
31 enum {
32 	MAX_PACKET_SIZE = 512,
33 	RELIABLE_HEADER_LEN = 8 // Only for CChannel_056b
34 };
35 
Clear()36 void CChannel::Clear()
37 {
38 	Socket = NULL;
39 	iPacketsDropped = 0;
40 	iPacketsGood = 0;
41 	cIncomingRate.clear();
42 	cOutgoingRate.clear();
43 	iOutgoingBytes = 0;
44 	iIncomingBytes = 0;
45 	iPing = 0;
46 	fLastSent = fLastPckRecvd = fLastPingSent = AbsTime();
47 	iCurrentIncomingBytes = 0;
48 	iCurrentOutgoingBytes = 0;
49 	Messages.clear();
50 
51 	ReliableStreamBandwidthCounter = 0.0f;
52 	ReliableStreamLastSentTime = tLX->currentTime;
53 	ReliableStreamBandwidthCounterLastUpdate = tLX->currentTime;
54 	LimitReliableStreamBandwidth( -1.0f, 5.0f, 1024.0f );
55 }
56 
57 ///////////////////
58 // Setup the channel
Create(const NetworkAddr & _adr,const SmartPointer<NetworkSocket> & _sock)59 void CChannel::Create(const NetworkAddr& _adr, const SmartPointer<NetworkSocket>& _sock)
60 {
61 	Clear();
62 	RemoteAddr = _adr;
63 	fLastPckRecvd = tLX->currentTime;
64 	Socket = _sock;
65 	fLastSent = AbsTime();
66 	fLastPingSent = fLastSent;
67 	iPing = 0;
68 }
69 
70 ////////////////////
71 // Adds a packet to reliable queue
AddReliablePacketToSend(CBytestream & bs)72 void CChannel::AddReliablePacketToSend(CBytestream& bs)
73 {
74 	if (bs.GetLength() > MAX_PACKET_SIZE - RELIABLE_HEADER_LEN)  {
75 		warnings
76 			<< "trying to send a reliable packet of size " << bs.GetLength()
77 			<< " which is bigger than allowed size (" << (MAX_PACKET_SIZE - RELIABLE_HEADER_LEN)
78 			<< "), packet might not be sent at all!" << endl;
79 		Messages.push_back(bs); // Try to send it anyway, perhaps we're lucky...
80 		return;
81 	}
82 
83 	if(bs.GetLength() == 0)
84 		return;
85 
86 	Messages.push_back(bs);
87 	// The messages are joined in Transmit() in one bigger packet, until it will hit bandwidth limit
88 }
89 
UpdateTransmitStatistics(int sentDataSize)90 void CChannel::UpdateTransmitStatistics( int sentDataSize )
91 {
92 	// Update statistics
93 	iOutgoingBytes += sentDataSize;
94 	iCurrentOutgoingBytes += sentDataSize;
95 	fLastSent = tLX->currentTime;
96 
97 	// Calculate the bytes per second
98 	cOutgoingRate.addData( tLX->currentTime, sentDataSize );
99 }
100 
UpdateReceiveStatistics(int receivedDataSize)101 void CChannel::UpdateReceiveStatistics( int receivedDataSize )
102 {
103 	// Got a packet (good or bad), update the received time
104 	fLastPckRecvd = tLX->currentTime;
105 
106 	// Update statistics - calculate the bytes per second
107 	// TODO: it was Bytestream->GetRestLen() before for iIncomingBytes and iCurrentIncomingBytes,
108 	// so skipped packet header, I think it's not that important, check this Albert and remove this TODO
109 	iIncomingBytes += receivedDataSize;
110 	iCurrentIncomingBytes += receivedDataSize;
111 	cIncomingRate.addData( tLX->currentTime, receivedDataSize );
112 }
113 
LimitReliableStreamBandwidth(float BandwidthLimit,float MaxPacketRate,float BandwidthCounterMaxValue)114 void CChannel::LimitReliableStreamBandwidth( float BandwidthLimit, float MaxPacketRate, float BandwidthCounterMaxValue )
115 {
116 	ReliableStreamBandwidthLimit = BandwidthLimit;
117 	ReliableStreamMaxPacketRate = MaxPacketRate;
118 	ReliableStreamBandwidthCounterMaxValue = BandwidthCounterMaxValue;
119 	// That's all, we won't reset ReliableStreamBandwidthCounter here
120 }
121 
UpdateReliableStreamBandwidthCounter()122 void CChannel::UpdateReliableStreamBandwidthCounter()
123 {
124 	ReliableStreamBandwidthCounter +=
125 		( tLX->currentTime - ReliableStreamBandwidthCounterLastUpdate ).seconds() *
126 		ReliableStreamBandwidthLimit;
127 
128 	ReliableStreamBandwidthCounterLastUpdate = tLX->currentTime;
129 
130 	if( ReliableStreamBandwidthCounter > ReliableStreamBandwidthCounterMaxValue )
131 		ReliableStreamBandwidthCounter = ReliableStreamBandwidthCounterMaxValue;
132 }
133 
CheckReliableStreamBandwidthLimit(float dataSizeToSend)134 bool CChannel::CheckReliableStreamBandwidthLimit( float dataSizeToSend )
135 {
136 	if( ReliableStreamBandwidthLimit <= 0 ) // No bandwidth limit
137 		return true;
138 
139 	if( ReliableStreamBandwidthCounter >= dataSizeToSend ||
140 		// Allow sending packets that exceed MaxValue, if Counter == MaxValue, then Counter will become negative
141 		ReliableStreamBandwidthCounter >= ReliableStreamBandwidthCounterMaxValue )
142 	{
143 		ReliableStreamBandwidthCounter -= dataSizeToSend;
144 		ReliableStreamLastSentTime = tLX->currentTime;
145 		return true;
146 	}
147 
148 	return false;
149 }
150 
ReliableStreamBandwidthLimitHit()151 bool CChannel::ReliableStreamBandwidthLimitHit()
152 {
153 	if( ReliableStreamBandwidthLimit <= 0 ||
154 		ReliableStreamBandwidthCounter >= ReliableStreamBandwidthCounterMaxValue / 2.0f ||
155 		ReliableStreamLastSentTime + 1.0f / ReliableStreamMaxPacketRate <= tLX->currentTime )
156 		return false;
157 	return true;
158 }
159 
160 ///////////////////
161 // CChannel for LX 0.56b implementation - LOSES PACKETS, and that cannot be fixed.
162 
Clear()163 void CChannel_056b::Clear()
164 {
165 	CChannel::Clear();
166 	iOutgoingSequence = 0;
167 	iReliableSequence = 0;
168 	iLast_ReliableSequence = 0;
169 	iIncoming_ReliableSequence = 0;
170 	iIncomingSequence = 0;
171 	iIncomingAcknowledged = 0;
172 	iOutgoingBytes = 0;
173 	iIncomingBytes = 0;
174 	fLastSent = AbsTime();
175 	bNewReliablePacket = false;
176 	iPongSequence = -1;
177 	Reliable.Clear();
178 }
179 
Create(const NetworkAddr & _adr,const SmartPointer<NetworkSocket> & _sock)180 void CChannel_056b::Create(const NetworkAddr& _adr, const SmartPointer<NetworkSocket>& _sock)
181 {
182 	Clear();
183 	CChannel::Create( _adr, _sock );
184 }
185 
186 ///////////////////
187 // Transmitt data, as well as handling reliable packets
Transmit(CBytestream * bs)188 void CChannel_056b::Transmit( CBytestream *bs )
189 {
190 	UpdateReliableStreamBandwidthCounter();
191 
192 	CBytestream outpack;
193 	Uint32 SendReliable = 0;
194 	ulong r1,r2;
195 
196 	// If the remote side dropped the last reliable packet, re-send it
197 	if( iIncomingAcknowledged > iLast_ReliableSequence &&
198 		iIncoming_ReliableAcknowledged != iReliableSequence &&
199 		CheckReliableStreamBandwidthLimit( (float)Reliable.GetLength() ) )
200 	{
201 		//hints << "Remote side dropped a reliable packet, resending..." << endl;
202 		SendReliable = 1;
203 	}
204 
205 
206 	// We send reliable message in these cases:
207 	// 1. The reliable buffer is empty, we copy the reliable message into it and send it
208 	// 2. We need to refresh ping
209 	if( Reliable.GetLength() == 0 &&
210 		! ReliableStreamBandwidthLimitHit() &&
211 		( !Messages.empty() || (tLX->currentTime >= fLastPingSent + 1.0f && iPongSequence == -1)))
212 	{
213 		while( ! Messages.empty() &&
214 				Reliable.GetLength() + Messages.front().GetLength() <= MAX_PACKET_SIZE - RELIABLE_HEADER_LEN &&
215 				CheckReliableStreamBandwidthLimit( (float)Messages.front().GetLength() ) )
216 		{
217 				Reliable.Append( & Messages.front() );
218 				Messages.pop_front();
219 		}
220 
221 		// XOR the reliable sequence
222 		iReliableSequence ^= 1;
223 
224 		// We got a reliable packet to send
225 		SendReliable = 1;
226 	}
227 
228 	// Create the reliable packet header
229 	r1 = iOutgoingSequence | (SendReliable << 31);
230 	r2 = iIncomingSequence | (iIncoming_ReliableSequence << 31);
231 
232 	iOutgoingSequence++;
233 
234 	outpack.writeInt(r1,4);
235 	outpack.writeInt(r2,4);
236 
237 
238 	// If were sending a reliable message, send it first
239 	if(SendReliable) {
240 		outpack.Append(&Reliable);
241 		iLast_ReliableSequence = iOutgoingSequence - 1;
242 
243 		// If we are sending a reliable message, remember this time and use it for ping calculations
244 		if (iPongSequence == -1)  {
245 			iPongSequence = iOutgoingSequence - 1;
246 			fLastPingSent = tLX->currentTime; //GetTime();
247 		}
248 
249 	}
250 
251 	// And add on the un reliable data if room in the packet struct
252 	if(bs) {
253 		if(outpack.GetLength() + bs->GetLength() < 4096) // Backward compatibility, the old bytestream has a fixed buffer of 4096 bytes
254 			outpack.Append(bs);
255 		else
256 			hints << "Not adding unrealiable data to avoid too big packets" << endl;
257 	}
258 
259 
260 	// Send the packet
261 	Socket->setRemoteAddress(RemoteAddr);
262 	outpack.Send(Socket.get());
263 
264 	UpdateTransmitStatistics( outpack.GetLength() );
265 }
266 
267 
268 ///////////////////
269 // Process channel (after receiving data)
Process(CBytestream * bs)270 bool CChannel_056b::Process(CBytestream *bs)
271 {
272 	Uint32 Sequence, SequenceAck;
273 	Uint32 ReliableAck, ReliableMessage;
274 	int drop;
275 
276 	// Start from the beginning of the packet
277 	bs->ResetPosToBegin();
278 	if( bs->GetLength() == 0 )
279 		return false;
280 
281 	UpdateReceiveStatistics( bs->GetLength() );
282 
283 	// Read the reliable packet header
284 	Sequence = bs->readInt(4);
285 	SequenceAck = bs->readInt(4);
286 
287 	// Get the reliable bits
288 	ReliableMessage = Sequence >> 31;
289 	ReliableAck = SequenceAck >> 31;
290 
291 	// Get rid of the reliable bits
292 	Sequence &= ~(1<<31);
293 	SequenceAck &= ~(1<<31);
294 
295 	// Get rid of the old packets
296 	// Small hack: there's a bug in old clients causing the first packet being ignored and resent later
297 	// It caused a delay when joining (especially on high-ping servers), this hack improves it
298 	if((Sequence <= iIncomingSequence) && (Sequence != 0 && iIncomingSequence != 0)) {
299 //		warnings << "Packet dropped" << endl;
300 //		bs->Dump();
301 		/*
302 		If we didn't ignore it here, we would become it
303 		again (the remote side will resend it because it thinks we've dropped
304 		the packet) and then parse it again => doubled text etc */
305 		// see GameServer::ReadPackets and CClient::ReadPackets
306 		// or perhaps it's ok to return true here but we should change the behaviour in *::ReadPackets
307 		return false;
308 	}
309 
310 
311 	// Check for dropped packets
312 	drop = Sequence - (iIncomingSequence+1);
313 	if(drop>0)
314 		// Update statistics
315 		iPacketsDropped++;
316 
317 
318 	// If the outgoing reliable message has been acknowledged, clear it for more reliable messages
319 	if(ReliableAck == iReliableSequence)
320 		Reliable.Clear();
321 
322 	// Check if pong has been acknowledged
323 	if(SequenceAck >= (size_t)iPongSequence)  {
324 		iPongSequence = -1;  // Ready for new pinging
325 		iPing = (int)((tLX->currentTime - fLastPingSent).milliseconds());
326 	}
327 
328 
329 	// If this packet contained a reliable message, update the sequences
330 	iIncomingSequence = Sequence;
331 	iIncomingAcknowledged = SequenceAck;
332 	iIncoming_ReliableAcknowledged = ReliableAck;
333 	if(ReliableMessage)  {
334 		iIncoming_ReliableSequence ^= 1;
335 		bNewReliablePacket = true;
336 	} else
337 		bNewReliablePacket = false;
338 
339 
340 	// Update the statistics
341 	iPacketsGood++;
342 
343 
344 	return true;
345 }
346 
347 
recheckSeqs()348 void CChannel_056b::recheckSeqs() {
349 	// Ensure the incoming sequence matchs the outgoing sequence
350 	if (this->getInSeq() >= this->getOutSeq())  {
351 		//if (chan->getInSeq() != chan->getOutSeq())
352 		//	warnings << cl->getWorm(0)->getName() << ": sequences not same (IN: " << chan->getInSeq() << ", OUT: " << chan->getOutSeq() << ")" << endl;
353 		//else
354 		//	hints << cl->getWorm(0)->getName() << ": sequences match!! (" << chan->getInSeq() << ")" << endl;*/
355 		this->setOutSeq(this->getInSeq());
356 	} else {
357 		// Sequences have slipped
358 		// Karel said: it's bullshit from JasonB, so we can ignore this warning :)
359 		//warnings << cl->getWorm(0)->getName() << ": sequences have slipped (IN: " << chan->getInSeq() << ", OUT: " << chan->getOutSeq() << ")" << endl;
360 		// TODO: Set the player's send_data property to false
361 	}
362 }
363 
364 
365 ///////////////////
366 // Reliable CChannel implementation by pelya ( I hope it's less messy, though it has more code ).
367 
368 /*
369 There are logical packets, each has it's own sequence number,
370 multiple logical packets can be transmitted in single net packet.
371 CChannel2::Process(CBytestream *) will return the logical packets one by one,
372 without merging them in one packet, to increase robustness.
373 It will modify CBytestream * argument for that.
374 The net packet format is:
375 	Acknowledged Packet Index 1 - 2 bytes, highest bit = 1
376 	...
377 	Acknowledged Packet Index N - 2 bytes, highest bit = 1
378 	Last Acknowledged Packet Index - 2 bytes, highest bit = 0 (marks end of acknowledged packets list) -
379 		 should be the lowest acknowledged sequence, all packets with lower
380 		 sequences are considered acknowledged.
381 	Packet Index 1 - 2 bytes, highest bit = 1
382 	Packet Size 1 - 2 bytes
383 	...
384 	Packet Index N - 2 bytes, highest bit = 1
385 	Packet Size N - 2 bytes
386 	Last Packet Index - 2 bytes, highest bit = 0 (marks end of packets list)
387 	Last Packet Size - 2 bytes, if we don't have reliable packet then Last Packet Size == 0, Last Packet Index ignored.
388 	Packets data
389 	Non-reliable packet data
390 
391 Only Last Acknowledged Packet Index and Last Packet Index are mandatory -
392 then CChannel will act like old CChannel_056b, when only one packet is allowed
393 to be flying through network at any time.
394 */
395 
396 enum {
397 
398 // SEQUENCE_WRAPAROUND is where sequence wraps to zero - sequence range is from 0 to SEQUENCE_WRAPAROUND-1.
399 // All sequences (or packet indexes) used are wrapping around at this number
400 // We cannot allow four leadinf 0xFF bytes in reliable packet, so SEQUENCE_WRAPAROUND
401 // is slightly less than 0x7FFF.
402 	SEQUENCE_WRAPAROUND = 32766,
403 
404 // SEQUENCE_SAFE_DIST is the max distance between two sequences when packets will get ignored as erroneous ones.
405 	SEQUENCE_SAFE_DIST = 100,
406 
407 // MAX_NON_ACKNOWLEDGED_PACKETS is max amount of packets that can be flying through the net at the same time.
408 	MAX_NON_ACKNOWLEDGED_PACKETS = 3,	// 1 is minimum - it behaves like old CChannel then.
409 
410 // SEQUENCE_HIGHEST_BIT is highest bit in a 2-byte int, for convenience.
411 	SEQUENCE_HIGHEST_BIT = 0x8000
412 };
413 
414 // How much to wait before sending another empty keep-alive packet, sec.
415 const float KEEP_ALIVE_PACKET_TIMEOUT = 1.0f;
416 
417 // How much to wait before sending data packet again, sec -
418 // if packets rarely get lost over net it will decrease bandwidth dramatically, for little lag tradeoff.
419 // Set to 0 to flood net with packets instantly as in CChannel_056b.
420 // If any new data available to send, or unreliable data present, packet is sent anyway.
421 // This is only inital value, it will get changed with time according to ping.
422 const float DATA_PACKET_TIMEOUT = 0.2f;
423 
424 // DataPacketTimeout = ping / DATA_PACKET_TIMEOUT_PING_COEFF,
425 // the bigger that value is, the more often channel will re-send data delayed in network.
426 const float DATA_PACKET_TIMEOUT_PING_COEFF = 1.5f;
427 
428 #ifdef DEBUG
429 const float DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY = 0.0f; // Self-explanatory
430 #endif
431 
432 // Do not check "if( sequence1 < sequence2 )", use this function instead, it will handle wraparound issues.
433 // SequenceDiff( 32765, 32764 ) equals to SequenceDiff( 0, 32765 ) equals to SequenceDiff( 1, 0 ) equals to 1.
SequenceDiff(int s1,int s2)434 int SequenceDiff( int s1, int s2 )
435 {
436 	int diff = s1 - s2;
437 	while( diff > SEQUENCE_WRAPAROUND / 2 - 1 )
438 		diff -= SEQUENCE_WRAPAROUND;
439 	while( diff < - (SEQUENCE_WRAPAROUND / 2) )
440 		diff += SEQUENCE_WRAPAROUND;
441 	return diff;
442 }
443 
Clear()444 void CChannel2::Clear()
445 {
446 	CChannel::Clear();
447 	Messages.clear();
448 	ReliableOut.clear();
449 	ReliableIn.clear();
450 	LastReliableOut = 0;
451 	LastAddedToOut = 0;
452 	LastReliableIn = 0;
453 	PongSequence = -1;
454 	LastReliablePacketSent = SEQUENCE_WRAPAROUND - 1;
455 	NextReliablePacketToSend = 0;
456 	LastReliableIn_SentWithLastPacket = SEQUENCE_WRAPAROUND - 1;
457 
458 	KeepAlivePacketTimeout = KEEP_ALIVE_PACKET_TIMEOUT;
459 	DataPacketTimeout = DATA_PACKET_TIMEOUT;
460 	MaxNonAcknowledgedPackets = MAX_NON_ACKNOWLEDGED_PACKETS;
461 
462 	#ifdef DEBUG
463 	DebugSimulateLaggyConnectionSendDelay = tLX->currentTime;
464 	#endif
465 };
466 
Create(const NetworkAddr & _adr,const SmartPointer<NetworkSocket> & _sock)467 void CChannel2::Create(const NetworkAddr& _adr, const SmartPointer<NetworkSocket>& _sock)
468 {
469 	Clear();
470 	CChannel::Create( _adr, _sock );
471 }
472 
473 // Get reliable packet from local buffer
GetPacketFromBuffer(CBytestream * bs)474 bool CChannel2::GetPacketFromBuffer(CBytestream *bs)
475 {
476 	if( ReliableIn.size() == 0 )
477 		return false;
478 
479 	int seqMin = LastReliableIn;
480 	PacketList_t::iterator itMin = ReliableIn.end();
481 	for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end(); it++ )
482 	{
483 		if( SequenceDiff( seqMin, it->second ) >= 0 )
484 		{
485 			seqMin = it->second;
486 			itMin = it;
487 		};
488 	};
489 	if( itMin != ReliableIn.end() )
490 	{
491 		*bs = itMin->first;
492 		ReliableIn.erase(itMin);
493 		return true;
494 	};
495 	return false;
496 }
497 
498 // This function will first return non-reliable data,
499 // and then one or many reliable packets - it will modify bs for that,
500 // so you should call it in a loop, clearing bs after each call.
Process(CBytestream * bs)501 bool CChannel2::Process(CBytestream *bs)
502 {
503 	bs->ResetPosToBegin();
504 	if( bs->GetLength() == 0 )
505 		return GetPacketFromBuffer(bs);
506 
507 	UpdateReceiveStatistics( bs->GetLength() );
508 
509 	// Acknowledged packets info processing
510 
511 	// Read acknowledged packets indexes
512 	unsigned seqAck = bs->readInt(2);
513 	std::vector< int > seqAckList;
514 	while( seqAck & SEQUENCE_HIGHEST_BIT )
515 	{
516 		seqAckList.push_back( seqAck & ~ SEQUENCE_HIGHEST_BIT );
517 		seqAck = bs->readInt(2);
518 	};
519 	if( SequenceDiff( seqAck, LastReliableOut ) < 0 || SequenceDiff( seqAck, LastReliableOut ) > SEQUENCE_SAFE_DIST )
520 	{
521 		iPacketsDropped++;	// Update statistics
522 		return GetPacketFromBuffer(bs);	// Packet from the past or from too distant future - ignore it.
523 	};
524 
525 	LastReliableOut = seqAck;
526 
527 	iPacketsGood++;	// Update statistics
528 
529 	// Delete acknowledged packets from buffer
530 	for( PacketList_t::iterator it = ReliableOut.begin(); it != ReliableOut.end(); )
531 	{
532 		bool erase = false;
533 		if( SequenceDiff( LastReliableOut, it->second ) >= 0 )
534 			erase = true;
535 		for( unsigned f=0; f<seqAckList.size(); f++ )
536 			if( seqAckList[f] == it->second )
537 				erase = true;
538 		if(erase)
539 			it = ReliableOut.erase(it);
540 		else
541 			it++;
542 	}
543 
544 	// Calculate ping ( with LastReliableOut, not with last packet - should be fair enough )
545 	if( PongSequence != -1 && SequenceDiff( LastReliableOut, PongSequence ) >= 0 )
546 	{
547 		iPing = (int) ((tLX->currentTime - fLastPingSent).milliseconds());
548 		PongSequence = -1;
549 		// Traffic shaping occurs here - change DataPacketTimeout according to received ping
550 		// Change the value slowly, to avoid peaks
551 		// TODO: I haven't really tested it this thing does any good, but it seems to work okay.
552 		DataPacketTimeout = ( iPing/1000.0f/DATA_PACKET_TIMEOUT_PING_COEFF + DataPacketTimeout*9.0f ) / 10.0f;
553 	};
554 
555 	// Processing of arrived data packets
556 
557 	// Read packets info
558 	std::vector< int > seqList;
559 	std::vector< int > seqSizeList;
560 	unsigned seq = bs->readInt(2);
561 	while( seq & SEQUENCE_HIGHEST_BIT )
562 	{
563 		seqList.push_back( seq & ~ SEQUENCE_HIGHEST_BIT );
564 		seqSizeList.push_back( bs->readInt(2) );
565 		seq = bs->readInt(2);
566 	};
567 	seqList.push_back( seq );
568 	seqSizeList.push_back( bs->readInt(2) );
569 
570 	// Put packets in buffer
571 	for( unsigned f=0; f<seqList.size(); f++ )
572 	{
573 		if( seqSizeList[f] == 0 ) // Last reliable packet may have size 0, if we're received non-reliable-only net packet
574 			continue;	// Just skip it, it's fake packet
575 
576 		bool addPacket = true;
577 		for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end() && addPacket; it++ )
578 			if( it->second == seqList[f] )
579 				addPacket = false;
580 		if( addPacket && SequenceDiff( seqList[f], LastReliableIn ) > 0 ) // Do not add packets from the past
581 		{	// Packet not in buffer yet - add it
582 			CBytestream bs1;
583 			bs1.writeData( bs->readData(seqSizeList[f]) );
584 			ReliableIn.push_back( std::make_pair( bs1, seqList[f] ) );
585 		}
586 		else	// Packet is in buffer already
587 		{
588 			// We may check here if arrived packet is the same as packet in buffer, and print errors.
589 			bs->Skip( seqSizeList[f] );
590 		};
591 	}
592 
593 	// Increase LastReliableIn until the first packet that is missing from sequence
594 	while( true )	// I just love such constructs :P don't worry, I've put "break" inside the loop.
595 	{
596 		bool nextPacketFound = false;
597 		int LastReliableInInc = LastReliableIn + 1;	// Next value of LastReliableIn
598 		if( LastReliableInInc >= SEQUENCE_WRAPAROUND )
599 			LastReliableInInc = 0;
600 		for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end() && !nextPacketFound; it++ )
601 			if( it->second == LastReliableInInc )
602 				nextPacketFound = true;
603 		if( nextPacketFound )
604 			LastReliableIn = LastReliableInInc;
605 		else
606 			break;
607 	};
608 
609 	if( bs->GetRestLen() > 0 )	// Non-reliable data left in this packet
610 		return true;	// Do not modify bs, allow user to read non-reliable data at the end of bs
611 
612 	if( GetPacketFromBuffer(bs) )	// We can return some reliable packet
613 		return true;
614 
615 	// We've got valid empty packet, or packet from future, return empty packet - bs->GetRestLen() == 0 here.
616 	// It is required to update server statistics, so clients that don't send packets won't timeout.
617 	return true;
618 };
619 
Transmit(CBytestream * unreliableData)620 void CChannel2::Transmit(CBytestream *unreliableData)
621 {
622 	UpdateReliableStreamBandwidthCounter();
623 
624 	#ifdef DEBUG
625 	// Very simple laggy connection emulation - send next packet once per DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY
626 	if( DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY > 0.0f )
627 	{
628 		if( DebugSimulateLaggyConnectionSendDelay > tLX->currentTime )
629 			return;
630 		DebugSimulateLaggyConnectionSendDelay = tLX->currentTime + DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY;
631 	}
632 	#endif
633 
634 	CBytestream bs;
635 	// Add acknowledged packets indexes
636 
637 	for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end(); it++ )
638 		if( SequenceDiff( it->second, LastReliableIn ) > 0 ) // Packets out of sequence
639 			bs.writeInt( it->second | SEQUENCE_HIGHEST_BIT, 2 );
640 
641 	bs.writeInt( LastReliableIn, 2 );
642 
643 	// Add reliable packet to ReliableOut buffer
644 	while( (int)ReliableOut.size() < MaxNonAcknowledgedPackets && ! Messages.empty() && ! ReliableStreamBandwidthLimitHit() )
645 	{
646 		LastAddedToOut ++ ;
647 		if( LastAddedToOut >= SEQUENCE_WRAPAROUND )
648 			LastAddedToOut = 0;
649 
650 		ReliableOut.push_back( std::make_pair( Messages.front(), LastAddedToOut ) );
651 		Messages.pop_front();
652 
653 		while( ! Messages.empty() &&
654 				ReliableOut.back().first.GetLength() + Messages.front().GetLength() <= MAX_PACKET_SIZE - RELIABLE_HEADER_LEN )
655 		{
656 			ReliableOut.back().first.Append( & Messages.front() );
657 			Messages.pop_front();
658 		}
659 	};
660 
661 	// Check if other side acknowledged packets with indexes bigger than NextReliablePacketToSend,
662 	// and roll NextReliablePacketToSend back to LastReliableOut.
663 	if( ! ReliableOut.empty() )
664 	{
665 		for( PacketList_t::iterator it = ReliableOut.begin(), it1 = it++; it != ReliableOut.end(); it1 = it++ )
666 		{
667 			if( SequenceDiff( it->second, it1->second ) != 1 )
668 				NextReliablePacketToSend = LastReliableOut;
669 		};
670 		if( ReliableOut.back().second != LastAddedToOut )
671 			NextReliablePacketToSend = LastReliableOut;
672 	};
673 
674 	// Timeout occured - other side didn't acknowledge our packets in time - re-send all of them from the first one.
675 	if( LastReliablePacketSent == LastAddedToOut &&
676 		SequenceDiff( LastReliablePacketSent, LastReliableOut ) >= MaxNonAcknowledgedPackets &&
677 		tLX->currentTime - fLastSent >= DataPacketTimeout )
678 	{
679 		NextReliablePacketToSend = LastReliableOut;
680 	}
681 
682 	// Add packet headers and data - send all packets with indexes from NextReliablePacketToSend and up.
683 	// Add older packets to the output first.
684 	// NextReliablePacketToSend points to the last packet.
685 	CBytestream packetData;
686 	bool unreliableOnly = true;
687 	bool firstPacket = true;	// Always send first packet, even if it bigger than MAX_PACKET_SIZE
688 	int packetIndex = LastReliableOut;
689 	int packetSize = 0;
690 
691 	for( PacketList_t::iterator it = ReliableOut.begin(); it != ReliableOut.end(); it++ )
692 	{
693 		if( SequenceDiff( it->second, NextReliablePacketToSend ) >= 0 )
694 		{
695 			if( ! CheckReliableStreamBandwidthLimit( (float)(it->first.GetLength() + 4) ) ||
696 				( bs.GetLength() + 4 + packetData.GetLength() + it->first.GetLength() > MAX_PACKET_SIZE && ! firstPacket ) )
697 				break;
698 
699 			if( !firstPacket )
700 			{
701 				bs.writeInt( packetIndex | SEQUENCE_HIGHEST_BIT, 2 );
702 				bs.writeInt( packetSize, 2 );
703 			};
704 			packetIndex = it->second;
705 			packetSize = it->first.GetLength();
706 
707 			firstPacket = false;
708 			unreliableOnly = false;
709 			NextReliablePacketToSend = it->second;
710 
711 			packetData.Append( &it->first );
712 		};
713 	};
714 
715 	bs.writeInt( packetIndex, 2 );
716 	bs.writeInt( packetSize, 2 );
717 
718 	bs.Append( &packetData );
719 
720 	if( unreliableOnly )
721 		bs.Append(unreliableData);
722 	else
723 	{
724 		if( bs.GetLength() + unreliableData->GetLength() <= MAX_PACKET_SIZE )
725 			bs.Append(unreliableData);
726 
727 		// If we are sending a reliable message, remember this time and use it for ping calculations
728 		if (PongSequence == -1)
729 		{
730 			PongSequence = NextReliablePacketToSend;
731 			fLastPingSent = tLX->currentTime;
732 		};
733 	};
734 
735 	if( unreliableData->GetLength() == 0 &&
736 		LastReliablePacketSent == LastAddedToOut &&
737 		tLX->currentTime - fLastSent < DataPacketTimeout )
738 	{
739 		// No unreliable data to send, and we've just sent the same packet -
740 		// send it again after some timeout, don't flood net.
741 		return;
742 	};
743 
744 	if( unreliableData->GetLength() == 0 && packetData.GetLength() == 0 &&
745 		LastReliableIn == LastReliableIn_SentWithLastPacket &&
746 		tLX->currentTime - fLastSent < KeepAlivePacketTimeout )
747 	{
748 		// Nothing to send really, send one empty packet per halfsecond so we won't timeout,
749 		// but always send first packet with acknowledges, or other side will flood
750 		// non-acknowledged packets for halfsecond.
751 		// CChannel_056b will always send packet on each frame, so we're conserving bandwidth compared to it, hehe.
752 
753 		cOutgoingRate.addData( tLX->currentTime, 0 );
754 		return;
755 	}
756 
757 	// Send the packet
758 	Socket->setRemoteAddress(RemoteAddr);
759 	bs.Send(Socket.get());
760 
761 	LastReliableIn_SentWithLastPacket = LastReliableIn;
762 	LastReliablePacketSent = NextReliablePacketToSend;
763 
764 	UpdateTransmitStatistics( bs.GetLength() );
765 }
766 
767 
768 ///////////////////
769 // Robustness test for CChannel
770 
printBinary(const std::string & s)771 std::string printBinary(const std::string & s)
772 {
773 	std::string r;
774 	char buf[10];
775 	for(size_t f=0; f<s.size(); f++)
776 	{
777 		sprintf( buf, "%02X ", (unsigned)( (unsigned char)s[f] ) );
778 		r += buf;
779 	}
780 	return r;
781 }
782 
TestCChannelRobustness()783 void TestCChannelRobustness()
784 {
785 	notes << "Testing CBytestream" << endl;
786 	CBytestream bsTest;
787 	bsTest.Test();
788 	notes << "\n\n\n\nTesting CChannel robustness" << endl;
789 	int lagMin = 50;
790 	int lagMax = 400;
791 	int packetLoss = 15; // In percents
792 	float packetsPerSecond1 = 10.0f; // One channel sends faster than another
793 	float packetsPerSecond2 = 0.2f;
794 	int packetExtraData = 8192; // Extra data in bytes to add to packet to check buffer overflows
795 
796 	CChannel3 c1, c2;	//CChannel_056b c1, c2;
797 	SmartPointer<NetworkSocket> s1 = new NetworkSocket(); s1->OpenUnreliable(0);
798 	SmartPointer<NetworkSocket> s2 = new NetworkSocket(); s2->OpenUnreliable(0);
799 	SmartPointer<NetworkSocket> s1lag = new NetworkSocket(); s1lag->OpenUnreliable(0);
800 	SmartPointer<NetworkSocket> s2lag = new NetworkSocket(); s2lag->OpenUnreliable(0);
801 	NetworkAddr a1, a2, a1lag, a2lag;
802 	a1 = s1->localAddress();
803 	a2 = s2->localAddress();
804 	a1lag = s1lag->localAddress();
805 	a2lag = s2lag->localAddress();
806 	c1.Create( a1lag, s1 );
807 	c2.Create( a2lag, s2 );
808 	s1lag->setRemoteAddress( a2 );
809 	s2lag->setRemoteAddress( a1 );
810 
811 	std::multimap< int, CBytestream > s1buf, s2buf;
812 
813 	int i1=0, i2=0, i1r=0, i2r=0;
814 	float packetDelay1 = 10000000;
815 	if( packetsPerSecond1 > 0 )
816 		packetDelay1 = 1000.0f / packetsPerSecond1;
817 	float packetDelay2 = 10000000;
818 	if( packetsPerSecond2 > 0 )
819 		packetDelay2 = 1000.0f / packetsPerSecond2;
820 	float nextPacket1 = 0;
821 	float nextPacket2 = 0;
822 	for( int testtime=0; testtime < 100000; testtime+= 10, nextPacket1 += 10, nextPacket2 += 10 )
823 	{
824 		tLX->currentTime = AbsTime(testtime);
825 
826 		// Transmit number sequence and some unreliable info
827 		CBytestream b1, b2, b1u, b2u;
828 
829 		if( nextPacket1 >= packetDelay1 )
830 		{
831 			nextPacket1 = 0;
832 			i1++;
833 			b1.writeInt(i1, 4);
834 			for( int f=0; f<packetExtraData; f++ )
835 				b1.writeByte(0xff);
836 			c1.AddReliablePacketToSend(b1);
837 		}
838 
839 		if( nextPacket2 >= packetDelay2 )
840 		{
841 			nextPacket2 = 0;
842 			i2++;
843 			b2.writeInt(i2, 4);
844 			for( int f=0; f<packetExtraData; f++ )
845 				b2.writeByte(0xff);
846 			c2.AddReliablePacketToSend(b2);
847 		}
848 
849 
850 		c1.Transmit( &b1u );
851 		c2.Transmit( &b2u );
852 
853 		b1.Clear();
854 		b2.Clear();
855 
856 		b1.Read(s1lag.get());
857 		b2.Read(s2lag.get());
858 		b1.ResetPosToBegin();
859 		b2.ResetPosToBegin();
860 
861 		// Add the lag
862 		if( b1.GetLength() != 0 )
863 		{
864 			if( GetRandomInt(100) + 1 < packetLoss )
865 				notes << testtime << ": c1 sent packet - lost (" << c1.Messages.size() <<
866 						" in buf): " << printBinary(b1.readData()) << endl;
867 			else
868 			{
869 				int lag = ((testtime + lagMin + GetRandomInt(lagMax-lagMin)) / 10)*10; // Round to 10
870 				s1buf.insert( std::make_pair( lag, b1 ) );
871 				notes<< testtime << ": c1 sent packet - lag " << lag << " size " << b1.GetLength() << " (" << c1.Messages.size() <<
872 						" in buf): " << printBinary(b1.readData()) << endl;
873 			}
874 		}
875 
876 		for( std::multimap< int, CBytestream > :: iterator it = s1buf.lower_bound(testtime);
877 				it != s1buf.upper_bound(testtime); it++ )
878 		{
879 			it->second.ResetPosToBegin();
880 			it->second.ResetPosToBegin();
881 			it->second.Send(s1lag.get());
882 		}
883 
884 		if( b2.GetLength() != 0 )
885 		{
886 			if( GetRandomInt(100) + 1 < packetLoss )
887 				notes << testtime << ": c2 sent packet - lost (" << c2.Messages.size() <<
888 						" in buf): " << printBinary(b2.readData()) << endl;
889 			else
890 			{
891 				int lag = ((testtime + lagMin + GetRandomInt(lagMax-lagMin)) / 10)*10; // Round to 10
892 				s2buf.insert( std::make_pair( lag, b2 ) );
893 				notes << testtime << ": c2 sent packet - lag " << lag << " size " << b2.GetLength() << " (" << c2.Messages.size() <<
894 						" in buf): " << printBinary(b2.readData()) << endl;
895 			}
896 		}
897 
898 		for( std::multimap< int, CBytestream > :: iterator it = s2buf.lower_bound(testtime);
899 				it != s2buf.upper_bound(testtime); it++ )
900 		{
901 			it->second.ResetPosToBegin();
902 			it->second.ResetPosToBegin();
903 			it->second.Send(s2lag.get());
904 		}
905 
906 		// Receive and check number sequence and unreliable info
907 		b1.Clear();
908 		b2.Clear();
909 
910 		b1.Read(s1.get());
911 		b2.Read(s2.get());
912 		b1.ResetPosToBegin();
913 		b2.ResetPosToBegin();
914 
915 		if( b1.GetLength() != 0 )
916 		{
917 			notes << testtime << ": c1 recv packet (ping " << c1.getPing() << "): " << printBinary(b1.readData()) << endl;
918 			b1.ResetPosToBegin();
919 			while( c1.Process( &b1 ) )
920 			{
921 				while( b1.GetRestLen() != 0 )
922 				{
923 					int i1rr = b1.readInt(4);
924 					notes << testtime << ": c1 reliable packet, data " << hex(i1rr) <<
925 							" expected " << i1r+1 << " - " << (i1rr == i1r+1 ? "good" : "ERROR!") << endl;
926 					i1r = i1rr;
927 					for( int f=0; f<packetExtraData; f++ )
928 						b1.readByte();
929 				}
930 				b1.Clear();
931 			}
932 		}
933 
934 		if( b2.GetLength() != 0 )
935 		{
936 			notes << testtime << ": c2 recv packet (ping " << c2.getPing() << "): " << printBinary(b2.readData()) << endl;
937 			b2.ResetPosToBegin();
938 			while( c2.Process( &b2 ) )
939 			{
940 				while( b2.GetRestLen() != 0 )
941 				{
942 					int i2rr = b2.readInt(4);
943 					notes << testtime << ": c2 reliable packet, data " << hex(i2rr) <<
944 							" expected " << i2r+1 << " - " << (i2rr == i2r+1 ? "good" : "ERROR!") << endl;
945 					i2r = i2rr;
946 					for( int f=0; f<packetExtraData; f++ )
947 						b2.readByte();
948 				}
949 				b2.Clear();
950 			}
951 		}
952 
953 	}
954 }
955 
956 /*
957 The format for packet is the same as with CChannel2, but with CRC16 added at the beginning,
958 and with indicator that packet is split into several smaller packets.
959 Packet won't contain four leading 0xFF because of CRC16, because two other bytes are acknowledged packet index.
960 
961 In case Packet Size highest bit = 1 ( SEQUENCE_HIGHEST_BIT ) that means we're transmitting big packet
962 split into several smaller packets. Sequence of packets with Packet Size highest bit = 1 and
963 one packet with Packet Size highest bit = 0 following it is assembled into one big logical packet for user.
964 */
965 
966 enum {
967 	MAX_FRAGMENTED_PACKET_SIZE = MAX_PACKET_SIZE - 24 // Actually 12 bytes are enough, but I want to have safety bound.
968 };
969 
970 Uint16 crc16(const char * buffer, size_t len, Uint16 crc = 0xffff); // Default non-zero value
971 
operator <(const Packet_t & p) const972 bool CChannel3::Packet_t::operator < ( const Packet_t & p ) const
973 {
974 	return SequenceDiff( idx, p.idx ) < 0;
975 };
976 
Clear()977 void CChannel3::Clear()
978 {
979 	CChannel::Clear();
980 	Messages.clear();
981 	ReliableOut.clear();
982 	ReliableIn.clear();
983 	LastReliableOut = 0;
984 	LastAddedToOut = 0;
985 	LastReliableIn = 0;
986 	PongSequence = -1;
987 	LastReliablePacketSent = SEQUENCE_WRAPAROUND - 1;
988 	NextReliablePacketToSend = 0;
989 	LastReliableIn_SentWithLastPacket = SEQUENCE_WRAPAROUND - 1;
990 
991 	KeepAlivePacketTimeout = KEEP_ALIVE_PACKET_TIMEOUT;
992 	DataPacketTimeout = DATA_PACKET_TIMEOUT;
993 	MaxNonAcknowledgedPackets = MAX_NON_ACKNOWLEDGED_PACKETS;
994 
995 	#ifdef DEBUG
996 	DebugSimulateLaggyConnectionSendDelay = tLX->currentTime;
997 	#endif
998 }
999 
Create(const NetworkAddr & _adr,const SmartPointer<NetworkSocket> & _sock)1000 void CChannel3::Create(const NetworkAddr& _adr, const SmartPointer<NetworkSocket>& _sock)
1001 {
1002 	Clear();
1003 	CChannel::Create( _adr, _sock );
1004 }
1005 
1006 // Get reliable packet from local buffer (merge fragmented packet)
GetPacketFromBuffer(CBytestream * bs)1007 bool CChannel3::GetPacketFromBuffer(CBytestream *bs)
1008 {
1009 	if( ReliableIn.size() == 0 )
1010 		return false;
1011 
1012 	bs->Clear();
1013 	PacketList_t::iterator it = ReliableIn.begin();
1014 	while( it != ReliableIn.end() && it->fragmented )
1015 	{
1016 		bs->Append( & it->data );
1017 		it++;
1018 	};
1019 	if( it != ReliableIn.end() && it->idx <= LastReliableIn )
1020 	{
1021 		bs->Append( & it->data );
1022 		it++;
1023 		ReliableIn.erase( ReliableIn.begin(), it );
1024 		return true;
1025 	}
1026 	bs->Clear();
1027 	return false;
1028 }
1029 
1030 // This function will first return non-reliable data,
1031 // and then one or many reliable packets - it will modify bs for that,
1032 // so you should call it in a loop, clearing bs after each call.
Process(CBytestream * bs)1033 bool CChannel3::Process(CBytestream *bs)
1034 {
1035 	bs->ResetPosToBegin();
1036 	if( bs->GetLength() == 0 )
1037 		return GetPacketFromBuffer(bs);
1038 
1039 	UpdateReceiveStatistics( bs->GetLength() );
1040 
1041 	// CRC16 check
1042 
1043 	unsigned crc = bs->readInt(2);
1044 	if( crc != crc16( bs->peekData( bs->GetRestLen() ).c_str(), bs->GetRestLen() ) )
1045 	{
1046 		iPacketsDropped++;	// Update statistics
1047 		return GetPacketFromBuffer(bs);	// Packet from the past or from too distant future - ignore it.
1048 	}
1049 
1050 	// Acknowledged packets info processing
1051 
1052 	// Read acknowledged packets indexes
1053 	unsigned seqAck = bs->readInt(2);
1054 	std::vector< int > seqAckList;
1055 	while( seqAck & SEQUENCE_HIGHEST_BIT )
1056 	{
1057 		seqAckList.push_back( seqAck & ~ SEQUENCE_HIGHEST_BIT );
1058 		seqAck = bs->readInt(2);
1059 	}
1060 	if( SequenceDiff( seqAck, LastReliableOut ) < 0 || SequenceDiff( seqAck, LastReliableOut ) > SEQUENCE_SAFE_DIST )
1061 	{
1062 		iPacketsDropped++;	// Update statistics
1063 		return GetPacketFromBuffer(bs);	// Packet from the past or from too distant future - ignore it.
1064 	}
1065 
1066 	LastReliableOut = seqAck;
1067 
1068 	iPacketsGood++;	// Update statistics
1069 
1070 	// Delete acknowledged packets from buffer
1071 	for( PacketList_t::iterator it = ReliableOut.begin(); it != ReliableOut.end(); )
1072 	{
1073 		bool erase = false;
1074 		if( SequenceDiff( LastReliableOut, it->idx ) >= 0 )
1075 			erase = true;
1076 		for( unsigned f=0; f<seqAckList.size(); f++ )
1077 			if( seqAckList[f] == it->idx )
1078 				erase = true;
1079 		if(erase)
1080 			it = ReliableOut.erase(it);
1081 		else
1082 			it++;
1083 	}
1084 
1085 	// Calculate ping ( with LastReliableOut, not with last packet - should be fair enough )
1086 	if( PongSequence != -1 && SequenceDiff( LastReliableOut, PongSequence ) >= 0 )
1087 	{
1088 		iPing = (int) ((tLX->currentTime - fLastPingSent).milliseconds());
1089 		PongSequence = -1;
1090 		// Traffic shaping occurs here - change DataPacketTimeout according to received ping
1091 		// Change the value slowly, to avoid peaks
1092 		DataPacketTimeout = ( iPing/1000.0f/DATA_PACKET_TIMEOUT_PING_COEFF + DataPacketTimeout*9.0f ) / 10.0f;
1093 	};
1094 
1095 	// Processing of arrived data packets
1096 
1097 	// Read packets info
1098 	std::vector< int > seqList;
1099 	std::vector< int > seqSizeList;
1100 	unsigned seq = bs->readInt(2);
1101 	while( seq & SEQUENCE_HIGHEST_BIT )
1102 	{
1103 		seqList.push_back( seq & ~ SEQUENCE_HIGHEST_BIT );
1104 		seqSizeList.push_back( bs->readInt(2) );
1105 		seq = bs->readInt(2);
1106 	}
1107 	seqList.push_back( seq );
1108 	seqSizeList.push_back( bs->readInt(2) );
1109 
1110 	// Put packets in buffer
1111 	for( unsigned f=0; f<seqList.size(); f++ )
1112 	{
1113 		if( seqSizeList[f] == 0 ) // Last reliable packet may have size 0, if we're received non-reliable-only net packet
1114 			continue;	// Just skip it, it's fake packet
1115 
1116 		bool addPacket = true;
1117 		for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end() && addPacket; it++ )
1118 			if( it->idx == seqList[f] )
1119 				addPacket = false;
1120 		if( addPacket && SequenceDiff( seqList[f], LastReliableIn ) > 0 ) // Do not add packets from the past
1121 		{	// Packet not in buffer yet - add it
1122 			CBytestream bs1;
1123 			bs1.writeData( bs->readData( seqSizeList[f] & ~ SEQUENCE_HIGHEST_BIT ) );
1124 			ReliableIn.push_back( Packet_t( bs1, seqList[f], (seqSizeList[f] & SEQUENCE_HIGHEST_BIT) != 0 ) );
1125 		}
1126 		else	// Packet is in buffer already
1127 		{
1128 			// We may check here if arrived packet is the same as packet in buffer, and print errors.
1129 			bs->Skip( seqSizeList[f] & ~ SEQUENCE_HIGHEST_BIT );
1130 		};
1131 	}
1132 
1133 	// Increase LastReliableIn until the first packet that is missing from sequence
1134 	while( true )	// I just love such constructs :P don't worry, I've put "break" inside the loop.
1135 	{
1136 		bool nextPacketFound = false;
1137 		int LastReliableInInc = LastReliableIn + 1;	// Next value of LastReliableIn
1138 		if( LastReliableInInc >= SEQUENCE_WRAPAROUND )
1139 			LastReliableInInc = 0;
1140 		for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end() && !nextPacketFound; it++ )
1141 			if( it->idx == LastReliableInInc )
1142 				nextPacketFound = true;
1143 		if( nextPacketFound )
1144 			LastReliableIn = LastReliableInInc;
1145 		else
1146 			break;
1147 	}
1148 
1149 	// The ReliableIn list updated - sort it
1150 	ReliableIn.sort();
1151 
1152 	if( bs->GetRestLen() > 0 )	// Non-reliable data left in this packet
1153 		return true;	// Do not modify bs, allow user to read non-reliable data at the end of bs
1154 
1155 	if( GetPacketFromBuffer(bs) )	// We can return some reliable packet
1156 		return true;
1157 
1158 	// We've got valid empty packet, or packet from future, return empty packet - bs->GetRestLen() == 0 here.
1159 	// It is required to update server statistics, so clients that don't send packets won't timeout.
1160 	return true;
1161 }
1162 
Transmit(CBytestream * unreliableData)1163 void CChannel3::Transmit(CBytestream *unreliableData)
1164 {
1165 	UpdateReliableStreamBandwidthCounter();
1166 
1167 	#ifdef DEBUG
1168 	// Very simple laggy connection emulation - send next packet once per DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY
1169 	if( DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY > 0.0f )
1170 	{
1171 		if( DebugSimulateLaggyConnectionSendDelay > tLX->currentTime )
1172 			return;
1173 		DebugSimulateLaggyConnectionSendDelay = tLX->currentTime + DEBUG_SIMULATE_LAGGY_CONNECTION_SEND_DELAY;
1174 	}
1175 	#endif
1176 
1177 	CBytestream bs;
1178 	// Add acknowledged packets indexes
1179 
1180 	for( PacketList_t::iterator it = ReliableIn.begin(); it != ReliableIn.end(); it++ )
1181 		if( SequenceDiff( it->idx, LastReliableIn ) > 0 ) // Packets out of sequence
1182 			bs.writeInt( it->idx | SEQUENCE_HIGHEST_BIT, 2 );
1183 
1184 	bs.writeInt( LastReliableIn, 2 );
1185 
1186 	// Add reliable packet to ReliableOut buffer
1187 	while( (int)ReliableOut.size() < MaxNonAcknowledgedPackets && !Messages.empty() && ! ReliableStreamBandwidthLimitHit() )
1188 	{
1189 		LastAddedToOut ++ ;
1190 		if( LastAddedToOut >= SEQUENCE_WRAPAROUND )
1191 			LastAddedToOut = 0;
1192 
1193 		if( Messages.front().GetLength() > MAX_FRAGMENTED_PACKET_SIZE )
1194 		{
1195 			// Fragment the packet
1196 			Messages.front().ResetPosToBegin();
1197 			CBytestream bs;
1198 			bs.writeData( Messages.front().readData( MAX_FRAGMENTED_PACKET_SIZE ) );
1199 			ReliableOut.push_back( Packet_t( bs, LastAddedToOut, true ) );
1200 			bs.Clear();
1201 			bs.writeData( Messages.front().readData() );
1202 			Messages.front() = bs;
1203 		}
1204 		else
1205 		{
1206 			ReliableOut.push_back( Packet_t( Messages.front(), LastAddedToOut, false ) );
1207 			Messages.pop_front();
1208 			while( ! Messages.empty() &&
1209 					ReliableOut.back().data.GetLength() + Messages.front().GetLength() <= MAX_FRAGMENTED_PACKET_SIZE )
1210 			{
1211 				ReliableOut.back().data.Append( & Messages.front() );
1212 				Messages.pop_front();
1213 			}
1214 		}
1215 	}
1216 
1217 	// Check if other side acknowledged packets with indexes bigger than NextReliablePacketToSend,
1218 	// and roll NextReliablePacketToSend back to LastReliableOut.
1219 	if( ! ReliableOut.empty() )
1220 	{
1221 		for( PacketList_t::iterator it = ReliableOut.begin(), it1 = it++; it != ReliableOut.end(); it1 = it++ )
1222 		{
1223 			if( SequenceDiff( it->idx, it1->idx ) != 1 )
1224 				NextReliablePacketToSend = LastReliableOut;
1225 		}
1226 		if( ReliableOut.back().idx != LastAddedToOut )
1227 			NextReliablePacketToSend = LastReliableOut;
1228 	}
1229 
1230 	// Timeout occured - other side didn't acknowledge our packets in time - re-send all of them from the first one.
1231 	if( LastReliablePacketSent == LastAddedToOut &&
1232 		SequenceDiff( LastReliablePacketSent, LastReliableOut ) >= MaxNonAcknowledgedPackets &&
1233 		tLX->currentTime - fLastSent >= DataPacketTimeout )
1234 	{
1235 		NextReliablePacketToSend = LastReliableOut;
1236 	}
1237 
1238 	// Add packet headers and data - send all packets with indexes from NextReliablePacketToSend and up.
1239 	// Add older packets to the output first.
1240 	// NextReliablePacketToSend points to the last packet.
1241 	CBytestream packetData;
1242 	bool unreliableOnly = true;
1243 	bool firstPacket = true;	// Always send first packet, even if it bigger than MAX_PACKET_SIZE
1244 								// This should not occur when packets are fragmented
1245 	int packetIndex = LastReliableOut;
1246 	int packetSize = 0;
1247 
1248 	for( PacketList_t::iterator it = ReliableOut.begin(); it != ReliableOut.end(); it++ )
1249 	{
1250 		if( SequenceDiff( it->idx, NextReliablePacketToSend ) >= 0 )
1251 		{
1252 			if( ! CheckReliableStreamBandwidthLimit( (float)(it->data.GetLength() + 4) ) ||
1253 				( bs.GetLength() + 4 + packetData.GetLength() + it->data.GetLength() > MAX_PACKET_SIZE-2 && !firstPacket ) )  // Substract CRC16 size
1254 				break;
1255 
1256 			if( !firstPacket )
1257 			{
1258 				bs.writeInt( packetIndex | SEQUENCE_HIGHEST_BIT, 2 );
1259 				bs.writeInt( packetSize, 2 );
1260 			};
1261 			packetIndex = it->idx;
1262 			packetSize = it->data.GetLength();
1263 			if( it->fragmented )
1264 				packetSize |= SEQUENCE_HIGHEST_BIT;
1265 
1266 			firstPacket = false;
1267 			unreliableOnly = false;
1268 			NextReliablePacketToSend = it->idx;
1269 
1270 			packetData.Append( &it->data );
1271 		}
1272 	}
1273 
1274 	bs.writeInt( packetIndex, 2 );
1275 	bs.writeInt( packetSize, 2 );
1276 
1277 	bs.Append( &packetData );
1278 
1279 	if( unreliableOnly )
1280 		bs.Append(unreliableData);
1281 	else
1282 	{
1283 		if( bs.GetLength() + unreliableData->GetLength() <= MAX_PACKET_SIZE-2 ) // Substract CRC16 size
1284 			bs.Append(unreliableData);
1285 
1286 		// If we are sending a reliable message, remember this time and use it for ping calculations
1287 		if (PongSequence == -1)
1288 		{
1289 			PongSequence = NextReliablePacketToSend;
1290 			fLastPingSent = tLX->currentTime;
1291 		}
1292 	}
1293 
1294 	if( unreliableData->GetLength() == 0 &&
1295 		LastReliablePacketSent == LastAddedToOut &&
1296 		tLX->currentTime - fLastSent < DataPacketTimeout )
1297 	{
1298 		// No unreliable data to send, and we've just sent the same packet -
1299 		// send it again after some timeout, don't flood net.
1300 		return;
1301 	}
1302 
1303 	if( unreliableData->GetLength() == 0 && packetData.GetLength() == 0 &&
1304 		LastReliableIn == LastReliableIn_SentWithLastPacket &&
1305 		tLX->currentTime - fLastSent < KeepAlivePacketTimeout )
1306 	{
1307 		// Nothing to send really, send one empty packet per halfsecond so we won't timeout,
1308 		// but always send first packet with acknowledges, or other side will flood
1309 		// non-acknowledged packets for halfsecond.
1310 		// CChannel_056b will always send packet on each frame, so we're conserving bandwidth compared to it, hehe.
1311 
1312 		cOutgoingRate.addData( tLX->currentTime, 0 );
1313 		return;
1314 	}
1315 
1316 	// Add CRC16
1317 
1318 	CBytestream bs1;
1319 	bs1.writeInt( crc16( bs.peekData( bs.GetLength() ).c_str(), bs.GetLength() ), 2);
1320 	bs1.Append(&bs);
1321 
1322 	// Send the packet
1323 	Socket->setRemoteAddress(RemoteAddr);
1324 	bs1.Send(Socket.get());
1325 
1326 	LastReliableIn_SentWithLastPacket = LastReliableIn;
1327 	LastReliablePacketSent = NextReliablePacketToSend;
1328 
1329 	UpdateTransmitStatistics( bs1.GetLength() );
1330 }
1331 
AddReliablePacketToSend(CBytestream & bs)1332 void CChannel3::AddReliablePacketToSend(CBytestream& bs) // The same as in CChannel but without error msg
1333 {
1334 	if(bs.GetLength() == 0)
1335 		return;
1336 
1337 	Messages.push_back(bs);
1338 	// The messages are joined in Transmit() in one bigger packet, until it will hit bandwidth limit
1339 }
1340 
1341 
1342 // CRC16 stolen from Linux kernel sources
1343 /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
1344 Uint16 const crc16_table[256] = {
1345         0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
1346         0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
1347         0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
1348         0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
1349         0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
1350         0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
1351         0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
1352         0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
1353         0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
1354         0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
1355         0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
1356         0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
1357         0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
1358         0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
1359         0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
1360         0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
1361         0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
1362         0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
1363         0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
1364         0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
1365         0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
1366         0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
1367         0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
1368         0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
1369         0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
1370         0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
1371         0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
1372         0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
1373         0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
1374         0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
1375         0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
1376         0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
1377 };
1378 
crc16_byte(Uint16 crc,const Uint8 data)1379 inline Uint16 crc16_byte(Uint16 crc, const Uint8 data)
1380 {
1381 	return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
1382 }
1383 
1384 /**
1385  * Compute the CRC-16 for the data buffer
1386  *
1387  * @param crc     previous CRC value
1388  * @param buffer  data pointer
1389  * @param len     number of bytes in the buffer
1390  * @return        the updated CRC value
1391  */
crc16(const char * buffer,size_t len,Uint16 crc)1392 Uint16 crc16(const char * buffer, size_t len, Uint16 crc )
1393 {
1394         while (len--)
1395 		{
1396                 crc = crc16_byte(crc, (Uint8)*buffer);
1397 				++buffer;
1398 		}
1399         return crc;
1400 }
1401 
1402