CONNECT.CPP 35 KB

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