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