forked from electronicarts/CnC_Remastered_Collection
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCONNECT.CPP
835 lines (720 loc) · 35.2 KB
/
CONNECT.CPP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
// software: you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
/* $Header: /CounterStrike/CONNECT.CPP 1 3/03/97 10:24a Joe_bostic $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : CONNECT.CPP *
* *
* Programmer : Bill Randolph *
* *
* Start Date : December 20, 1994 *
* *
* Last Update : May 31, 1995 [BRR] *
*-------------------------------------------------------------------------*
* Functions: *
* ConnectionClass::ConnectionClass -- class constructor *
* ConnectionClass::~ConnectionClass -- class destructor *
* ConnectionClass::Init -- Initializes connection queue to empty *
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
* ConnectionClass::Service -- main polling routine; services packets *
* ConnectionClass::Service_Send_Queue -- services the send queue *
* ConnectionClass::Service_Receive_Queue -- services receive queue *
* ConnectionClass::Time -- gets current time *
* ConnectionClass::Command_Name -- returns name for a packet command *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
#include <stdio.h>
//#include <mem.h>
#include <sys\timeb.h>
#include "connect.h"
//#include "WolDebug.h"
/*
********************************* Globals ***********************************
*/
char *ConnectionClass::Commands[PACKET_COUNT] = {
"ADATA",
"NDATA",
"ACK"
};
/***************************************************************************
* ConnectionClass::ConnectionClass -- class constructor *
* *
* INPUT: *
* numsend desired # of entries for the send queue *
* numreceive desired # of entries for the receive queue *
* maxlen max length of an application packet *
* magicnum the packet "magic number" for this connection *
* retry_delta the time to wait between sends *
* max_retries the max # of retries allowed for a packet *
* (-1 means retry forever, based on this parameter) *
* timeout the max amount of time before we give up on a packet *
* (-1 means retry forever, based on this parameter) *
* extralen max size of app-specific extra bytes (optional) *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
ConnectionClass::ConnectionClass (int numsend, int numreceive,
int maxlen, unsigned short magicnum, unsigned long retry_delta,
unsigned long max_retries, unsigned long timeout, int extralen)
{
/*------------------------------------------------------------------------
Compute our maximum packet length
------------------------------------------------------------------------*/
MaxPacketLen = maxlen + sizeof(CommHeaderType);
/*------------------------------------------------------------------------
Assign the magic number
------------------------------------------------------------------------*/
MagicNum = magicnum;
/*------------------------------------------------------------------------
Initialize the retry time. This is the time that t2 - t1 must be greater
than before a retry will occur.
------------------------------------------------------------------------*/
RetryDelta = retry_delta;
/*------------------------------------------------------------------------
Set the maximum allowable retries.
------------------------------------------------------------------------*/
MaxRetries = max_retries;
/*------------------------------------------------------------------------
Set the timeout for this connection.
------------------------------------------------------------------------*/
Timeout = timeout;
/*------------------------------------------------------------------------
Allocate the packet staging buffer. This will be used to
------------------------------------------------------------------------*/
PacketBuf = new char[ MaxPacketLen ];
/*------------------------------------------------------------------------
Allocate the packet Queue. This will store incoming packets (placed there
by Receive_Packet), and outgoing packets (placed there by Send_Packet).
It can optionally store "extra" bytes, which are stored along with each
packet, but aren't transmitted as part of the packet. If 'extralen'
is 0, the CommBufferClass ignores this parameter.
------------------------------------------------------------------------*/
Queue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);
} /* end of ConnectionClass */
/***************************************************************************
* ConnectionClass::~ConnectionClass -- class destructor *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
ConnectionClass::~ConnectionClass ()
{
/*------------------------------------------------------------------------
Free memory.
------------------------------------------------------------------------*/
delete [] PacketBuf;
delete Queue;
} /* end of ~ConnectionClass */
/***************************************************************************
* ConnectionClass::Init -- Initializes connection queue to empty *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
void ConnectionClass::Init (void)
{
NumRecNoAck = 0;
NumRecAck = 0;
NumSendNoAck = 0;
NumSendAck = 0;
LastSeqID = 0xffffffff;
LastReadID = 0xffffffff;
Queue->Init();
} /* end of Init */
/***************************************************************************
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
* *
* This routine prefixes the given buffer with a CommHeaderType and *
* queues the resulting packet into the Send Queue. (It's actually the *
* Service() routine that handles the hardware-dependent Send of the data).*
* The packet's MagicNumber, Code, and PacketID are set here. *
* *
* INPUT: *
* buf buffer to send *
* buflen length of buffer *
* ack_req 1 = ACK is required for this packet; 0 = isn't *
* *
* OUTPUT: *
* 1 = packet was queue'd OK, 0 = wasn't *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)
{
/*------------------------------------------------------------------------
Set the magic # for the packet
------------------------------------------------------------------------*/
((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;
/*------------------------------------------------------------------------
Set the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't
Set the packet ID to the appropriate counter value.
------------------------------------------------------------------------*/
if (ack_req) {
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;
((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;
}
else {
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;
((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;
}
/*------------------------------------------------------------------------
Now build the packet
------------------------------------------------------------------------*/
memcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);
/*------------------------------------------------------------------------
Add it to the queue; don't add any extra data with it.
------------------------------------------------------------------------*/
if (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {
if (ack_req) {
NumSendAck++;
}
else {
NumSendNoAck++;
}
return(1);
}
else {
return(0);
}
} /* end of Send_Packet */
/***************************************************************************
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
* *
* INPUT: *
* buf buffer to process (already includes CommHeaderType) *
* buflen length of buffer to process *
* *
* OUTPUT: *
* 1 = packet was processed OK, 0 = error *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Receive_Packet (void * buf, int buflen)
{
CommHeaderType *packet; // ptr to packet header
SendQueueType *send_entry; // ptr to send entry header
ReceiveQueueType *rec_entry; // ptr to recv entry header
CommHeaderType *entry_data; // ptr to queue entry data
CommHeaderType ackpacket; // ACK packet to send
int i;
int save_packet = 1; // 0 = this is a resend
int found;
/*------------------------------------------------------------------------
Check the magic #
------------------------------------------------------------------------*/
packet = (CommHeaderType *)buf;
if (packet->MagicNumber != MagicNum) {
return(0);
}
/*------------------------------------------------------------------------
Handle an incoming ACK
------------------------------------------------------------------------*/
if (packet->Code == PACKET_ACK) {
for (i = 0; i < Queue->Num_Send(); i++) {
/*..................................................................
Get queue entry ptr
..................................................................*/
send_entry = Queue->Get_Send(i);
/*..................................................................
If ptr is valid, get ptr to its data
..................................................................*/
if (send_entry != NULL) {
entry_data = (CommHeaderType *)send_entry->Buffer;
/*...............................................................
If ACK is for this entry, mark it
...............................................................*/
if (packet->PacketID==entry_data->PacketID &&
entry_data->Code == PACKET_DATA_ACK) {
send_entry->IsACK = 1;
break;
}
}
}
return(1);
}
/*------------------------------------------------------------------------
Handle an incoming PACKET_DATA_NOACK packet
------------------------------------------------------------------------*/
else if (packet->Code == PACKET_DATA_NOACK) {
/*.....................................................................
If there's only one slot left, don't tie up the queue with this packet
.....................................................................*/
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
return(0);
}
/*.....................................................................
Error if we can't queue the packet
.....................................................................*/
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
return(0);
}
NumRecNoAck++;
return(1);
}
/*------------------------------------------------------------------------
Handle an incoming PACKET_DATA_ACK packet
------------------------------------------------------------------------*/
else if (packet->Code == PACKET_DATA_ACK) {
/*.....................................................................
If this is a packet requires an ACK, and it's ID is older than our
"oldest" ID, we know it's a resend; send an ACK, but don't queue it
.....................................................................*/
if (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {
save_packet = 0;
}
/*.....................................................................
Otherwise, scan the queue for this entry; if it's found, it's a
resend, so don't save it.
.....................................................................*/
else {
save_packet = 1;
for (i = 0; i < Queue->Num_Receive(); i++) {
rec_entry = Queue->Get_Receive(i);
if (rec_entry) {
entry_data = (CommHeaderType *)rec_entry->Buffer;
/*...........................................................
Packet is found; it's a resend
...........................................................*/
if (entry_data->Code == PACKET_DATA_ACK &&
entry_data->PacketID == packet->PacketID) {
save_packet = 0;
break;
}
}
}
} /* end of scan for resend */
/*.....................................................................
Queue the packet & update our LastSeqID value.
.....................................................................*/
if (save_packet) {
/*..................................................................
If there's only one slot left, make sure we only put a packet in it
if this packet will let us increment our LastSeqID; otherwise, we'll
get stuck, forever unable to increment LastSeqID.
..................................................................*/
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
if (packet->PacketID != (LastSeqID + 1) ) {
return(0);
}
}
/*..................................................................
If we can't queue the packet, return; don't send an ACK.
..................................................................*/
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
return(0);
}
NumRecAck++;
/*..................................................................
Update our LastSeqID value if we can. Anything less than LastSeqID
we'll know is a resend.
..................................................................*/
if (packet->PacketID == (LastSeqID + 1)) {
LastSeqID = packet->PacketID;
/*...............................................................
Now that we have a new 'LastSeqID', search our Queue to see if
the next ID is there; if so, keep checking for the next one;
break only when the next one isn't found. This forces
LastSeqID to be the largest possible value.
...............................................................*/
do {
found = 0;
for (i = 0; i < Queue->Num_Receive(); i++) {
rec_entry = Queue->Get_Receive(i);
if (rec_entry) {
entry_data = (CommHeaderType *)rec_entry->Buffer;
/*......................................................
Entry is found
......................................................*/
if (entry_data->Code == PACKET_DATA_ACK &&
entry_data->PacketID == (LastSeqID + 1)) {
LastSeqID = entry_data->PacketID;
found = 1;
break;
}
}
}
} while (found);
}
} /* end of save packet */
/*.....................................................................
Send an ACK, regardless of whether this was a resend or not.
.....................................................................*/
ackpacket.MagicNumber = Magic_Num();
ackpacket.Code = PACKET_ACK;
ackpacket.PacketID = packet->PacketID;
Send ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);
return(1);
}
return(0);
} /* end of Receive_Packet */
/***************************************************************************
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
* *
* INPUT: *
* buf location to store buffer *
* buflen filled in with length of 'buf' *
* *
* OUTPUT: *
* 1 = packet was read, 0 = wasn't *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Get_Packet (void * buf, int *buflen)
{
ReceiveQueueType *rec_entry; // ptr to receive entry header
int packetlen; // size of received packet
CommHeaderType *entry_data;
int i;
/*------------------------------------------------------------------------
Ensure that we read the packets in order. LastReadID is the ID of the
last PACKET_DATA_ACK packet we read.
------------------------------------------------------------------------*/
for (i = 0; i < Queue->Num_Receive(); i++) {
rec_entry = Queue->Get_Receive(i);
/*.....................................................................
Only read this entry if it hasn't been yet
.....................................................................*/
if (rec_entry && rec_entry->IsRead==0) {
entry_data = (CommHeaderType *)rec_entry->Buffer;
/*..................................................................
If this is a DATA_ACK packet, its ID must be one greater than
the last one we read.
..................................................................*/
if ( (entry_data->Code == PACKET_DATA_ACK) &&
(entry_data->PacketID == (LastReadID + 1))) {
LastReadID = entry_data->PacketID;
rec_entry->IsRead = 1;
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
if (packetlen > 0) {
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
packetlen);
}
(*buflen) = packetlen;
return(1);
}
/*..................................................................
If this is a DATA_NOACK packet, who cares what the ID is?
..................................................................*/
else if (entry_data->Code == PACKET_DATA_NOACK) {
rec_entry->IsRead = 1;
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
if (packetlen > 0) {
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
packetlen);
}
(*buflen) = packetlen;
return(1);
}
}
}
return(0);
} /* end of Get_Packet */
/***************************************************************************
* ConnectionClass::Service -- main polling routine; services packets *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 1 = OK, 0 = error (connection is broken!) *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Service (void)
{
/*------------------------------------------------------------------------
Service the Send Queue: This [re]sends packets in the Send Queue which
haven't been ACK'd yet, and if their retry timeout has expired, and
updates the FirstTime, LastTime & SendCount values in the Queue entry.
Entries that have been ACK'd should be removed.
Service the Receive Queue: This sends ACKs for packets that haven't
been ACK'd yet. Entries that the app has read, and have been ACK'd,
should be removed.
------------------------------------------------------------------------*/
if ( Service_Send_Queue() && Service_Receive_Queue() ) {
return(1);
}
else {
return(0);
}
} /* end of Service */
/***************************************************************************
* ConnectionClass::Service_Send_Queue -- services the send queue *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 1 = OK, 0 = error *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Service_Send_Queue (void)
{
int i;
int num_entries;
SendQueueType *send_entry; // ptr to send queue entry
CommHeaderType *packet_hdr; // packet header
unsigned long curtime; // current time
int bad_conn = 0;
/*------------------------------------------------------------------------
Remove any ACK'd packets from the queue
------------------------------------------------------------------------*/
for (i = 0; i < Queue->Num_Send(); i++) {
/*.....................................................................
Get this queue entry
.....................................................................*/
send_entry = Queue->Get_Send(i);
/*.....................................................................
If ACK has been received, unqueue it
.....................................................................*/
if (send_entry->IsACK) {
/*..................................................................
Update this queue's response time
..................................................................*/
packet_hdr = (CommHeaderType *)send_entry->Buffer;
if (packet_hdr->Code == PACKET_DATA_ACK) {
Queue->Add_Delay(Time() - send_entry->FirstTime);
}
/*..................................................................
Unqueue the packet
..................................................................*/
Queue->UnQueue_Send(NULL,NULL,i,NULL,NULL);
i--;
}
}
/*------------------------------------------------------------------------
Loop through all entries in the Send queue. [Re]Send any entries that
need it.
------------------------------------------------------------------------*/
num_entries = Queue->Num_Send();
for (i = 0; i < num_entries; i++) {
send_entry = Queue->Get_Send(i);
if (send_entry->IsACK) {
continue;
}
/*.....................................................................
Only send the message if time has elapsed. (The message's Time
fields are init'd to 0 when a message is queue'd or unqueue'd, so the
first time through, the delta time will appear large.)
.....................................................................*/
curtime = Time();
if (curtime - send_entry->LastTime > RetryDelta) {
/*..................................................................
Send the message
..................................................................*/
Send (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,
send_entry->ExtraLen);
/*..................................................................
Fill in Time fields
..................................................................*/
send_entry->LastTime = curtime;
if (send_entry->SendCount==0) {
send_entry->FirstTime = curtime;
/*...............................................................
If this is the 1st time we're sending this packet, and it doesn't
require an ACK, mark it as ACK'd; then, the next time through,
it will just be removed from the queue.
...............................................................*/
packet_hdr = (CommHeaderType *)send_entry->Buffer;
if (packet_hdr->Code == PACKET_DATA_NOACK) {
send_entry->IsACK = 1;
}
}
/*..................................................................
Update SendCount
..................................................................*/
send_entry->SendCount++;
/*..................................................................
Perform error detection, based on either MaxRetries or Timeout
..................................................................*/
if (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {
bad_conn = 1;
}
if (Timeout != -1 &&
(send_entry->LastTime - send_entry->FirstTime) > Timeout) {
bad_conn = 1;
}
}
}
/*------------------------------------------------------------------------
If the connection is going bad, return an error
------------------------------------------------------------------------*/
if (bad_conn) {
return(0);
}
else {
return(1);
}
} /* end of Service_Send_Queue */
/***************************************************************************
* ConnectionClass::Service_Receive_Queue -- services receive queue *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 1 = OK, 0 = error *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
int ConnectionClass::Service_Receive_Queue (void)
{
ReceiveQueueType *rec_entry; // ptr to receive entry header
CommHeaderType *packet_hdr; // packet header
int i;
/*------------------------------------------------------------------------
Remove all dead packets.
PACKET_DATA_NOACK: if it's been read, throw it away.
PACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,
throw it away.
------------------------------------------------------------------------*/
for (i = 0; i < Queue->Num_Receive(); i++) {
rec_entry = Queue->Get_Receive(i);
if (rec_entry->IsRead) {
packet_hdr = (CommHeaderType *)(rec_entry->Buffer);
if (packet_hdr->Code == PACKET_DATA_NOACK) {
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
i--;
}
else if (packet_hdr->PacketID < LastSeqID) {
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
i--;
}
}
}
return(1);
} /* end of Service_Receive_Queue */
/***************************************************************************
* ConnectionClass::Time -- gets current time *
* *
* INPUT: *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 12/20/1994 BR : Created. *
*=========================================================================*/
unsigned long ConnectionClass::Time (void)
{
static struct timeb mytime; // DOS time
unsigned long msec;
#ifdef WWLIB32_H
/*------------------------------------------------------------------------
If the Westwood timer system has been activated, use TickCount's value
------------------------------------------------------------------------*/
if (TimerSystemOn) {
return(TickCount); // Westwood Library time
}
/*------------------------------------------------------------------------
Otherwise, use the DOS timer
------------------------------------------------------------------------*/
else {
ftime(&mytime);
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
return((msec / 100) * 6);
}
#else
/*------------------------------------------------------------------------
If the Westwood library isn't being used, use the DOS timer.
------------------------------------------------------------------------*/
ftime(&mytime);
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
return((msec / 100) * 6);
#endif
} /* end of Time */
/***************************************************************************
* ConnectionClass::Command_Name -- returns name for given packet command *
* *
* INPUT: *
* command packet Command value to get name for *
* *
* OUTPUT: *
* ptr to command name, NULL if invalid *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 05/31/1995 BRR : Created. *
*=========================================================================*/
char *ConnectionClass::Command_Name(int command)
{
if (command >= 0 && command < PACKET_COUNT) {
return(Commands[command]);
}
else {
return(NULL);
}
} /* end of Command_Name */
/************************** end of connect.cpp *****************************/