CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

COMBUF.CPP (51155B)


      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/COMBUF.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 : COMBUF.CPP                             	*
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : December 19, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : October 23, 1995 [BRR]                   *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Functions:                                                              *
     33  *   CommBufferClass::CommBufferClass -- class constructor           		*
     34  *   CommBufferClass::~CommBufferClass -- class destructor           		*
     35  *   CommBufferClass::Init -- initializes this queue                       *
     36  *   CommBufferClass::Init_Send_Queue -- Clears the send queue             *
     37  *   CommBufferClass::Queue_Send -- queues a message for sending           *
     38  *   CommBufferClass::UnQueue_Send -- removes next entry from send queue	*
     39  *   CommBufferClass::Get_Send -- gets ptr to queue entry                  *
     40  *   CommBufferClass::Queue_Receive -- queues a received message				*
     41  *   CommBufferClass::UnQueue_Receive -- removes next entry from send queue*
     42  *   CommBufferClass::Get_Receive -- gets ptr to queue entry               *
     43  *   CommBufferClass::Add_Delay -- adds a new delay value for response time*
     44  *   CommBufferClass::Avg_Response_Time -- returns average response time  	*
     45  *   CommBufferClass::Max_Response_Time -- returns max response time  		*
     46  *   CommBufferClass::Reset_Response_Time -- resets computations				*
     47  *   Mono_Debug_Print -- Debug output routine                              *
     48  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     49 
     50 
     51 #include	"function.h"
     52 #include <stdio.h>
     53 //#include <mem.h>
     54 #include "combuf.h"
     55 #include "connect.h"	// for command names for debug output
     56 #include "wwlib32.h"	// to enable mono output
     57 
     58 
     59 /***************************************************************************
     60  * CommBufferClass::CommBufferClass -- class constructor             		*
     61  *                                                                         *
     62  * INPUT:                                                                  *
     63  *		numsend		# queue entries for sending										*
     64  *		numreceive	# queue entries for receiving										*
     65  *		maxlen		maximum desired packet length, in bytes						*
     66  *		extralen		max size of app-specific extra bytes (optional)				*
     67  *                                                                         *
     68  * OUTPUT:                                                                 *
     69  *		none.																						*
     70  *                                                                         *
     71  * WARNINGS:                                                               *
     72  *		none.																						*
     73  *                                                                         *
     74  * HISTORY:                                                                *
     75  *   12/19/1994 BR : Created.                                              *
     76  *=========================================================================*/
     77 CommBufferClass::CommBufferClass(int numsend, int numreceive, int maxlen,
     78 	int extralen)
     79 {
     80 	int i;
     81 
     82 	//------------------------------------------------------------------------
     83 	//	Init variables
     84 	//------------------------------------------------------------------------
     85 	MaxSend = numsend;
     86 	MaxReceive = numreceive;
     87 	MaxPacketSize = maxlen;
     88 	MaxExtraSize = extralen;
     89 
     90 	//------------------------------------------------------------------------
     91 	//	Allocate the queue entries
     92 	//------------------------------------------------------------------------
     93 	SendQueue = new SendQueueType[numsend];
     94 	ReceiveQueue = new ReceiveQueueType[numreceive];
     95 
     96 	SendIndex = new int[numsend];
     97 	ReceiveIndex = new int[numreceive];
     98 
     99 	//------------------------------------------------------------------------
    100 	//	Allocate queue entry buffers
    101 	//------------------------------------------------------------------------
    102 	for (i = 0; i < MaxSend; i++) {
    103 		SendQueue[i].Buffer = new char[maxlen];
    104 		if (MaxExtraSize > 0) {
    105 			SendQueue[i].ExtraBuffer = new char[MaxExtraSize];
    106 		}
    107 		else {
    108 			SendQueue[i].ExtraBuffer = NULL;
    109 		}
    110 	}
    111 
    112 	for (i = 0; i < MaxReceive; i++) {
    113 		ReceiveQueue[i].Buffer = new char[maxlen];
    114 		if (MaxExtraSize > 0) {
    115 			ReceiveQueue[i].ExtraBuffer = new char[MaxExtraSize];
    116 		}
    117 		else {
    118 			ReceiveQueue[i].ExtraBuffer = NULL;
    119 		}
    120 	}
    121 
    122 	Init();
    123 
    124 }	/* end of CommBufferClass */
    125 
    126 
    127 /***************************************************************************
    128  * CommBufferClass::~CommBufferClass -- class destructor             		*
    129  *                                                                         *
    130  * INPUT:                                                                  *
    131  *		none.																						*
    132  *                                                                         *
    133  * OUTPUT:                                                                 *
    134  *		none.																						*
    135  *                                                                         *
    136  * WARNINGS:                                                               *
    137  *		none.																						*
    138  *                                                                         *
    139  * HISTORY:                                                                *
    140  *   12/19/1994 BR : Created.                                              *
    141  *=========================================================================*/
    142 CommBufferClass::~CommBufferClass()
    143 {
    144 	int i;
    145 
    146 	//------------------------------------------------------------------------
    147 	//	Free queue entry buffers
    148 	//------------------------------------------------------------------------
    149 	for (i = 0; i < MaxSend; i++) {
    150 		delete [] SendQueue[i].Buffer;
    151 		if (SendQueue[i].ExtraBuffer) {
    152 			delete [] SendQueue[i].ExtraBuffer;
    153 		}
    154 	}
    155 
    156 	for (i = 0; i < MaxReceive; i++) {
    157 		delete [] ReceiveQueue[i].Buffer;
    158 		if (ReceiveQueue[i].ExtraBuffer) {
    159 			delete [] ReceiveQueue[i].ExtraBuffer;
    160 		}
    161 	}
    162 
    163 	delete [] SendQueue;
    164 	delete [] ReceiveQueue;
    165 
    166 	delete [] SendIndex;
    167 	delete [] ReceiveIndex;
    168 
    169 }	/* end of ~CommBufferClass */
    170 
    171 
    172 /***************************************************************************
    173  * CommBufferClass::Init -- initializes this queue                         *
    174  *                                                                         *
    175  * INPUT:                                                                  *
    176  *		none.																						*
    177  *                                                                         *
    178  * OUTPUT:                                                                 *
    179  *		none.																						*
    180  *                                                                         *
    181  * WARNINGS:                                                               *
    182  *		none.																						*
    183  *                                                                         *
    184  * HISTORY:                                                                *
    185  *   01/20/1995 BR : Created.                                              *
    186  *=========================================================================*/
    187 void CommBufferClass::Init(void)
    188 {
    189 	int i;
    190 
    191 	//------------------------------------------------------------------------
    192 	//	Init data members
    193 	//------------------------------------------------------------------------
    194 	SendTotal = 0L;
    195 	ReceiveTotal = 0L;
    196 
    197 	DelaySum = 0L;
    198 	NumDelay = 0L;
    199 	MeanDelay = 0L;
    200 	MaxDelay = 0L;
    201 
    202 	SendCount = 0;
    203 
    204 	ReceiveCount = 0;
    205 
    206 	//------------------------------------------------------------------------
    207 	//	Init the queue entries
    208 	//------------------------------------------------------------------------
    209 	for (i = 0; i < MaxSend; i++) {
    210 		SendQueue[i].IsActive = 0;
    211 		SendQueue[i].IsACK = 0;
    212 		SendQueue[i].FirstTime = 0L;
    213 		SendQueue[i].LastTime = 0L;
    214 		SendQueue[i].SendCount = 0L;
    215 		SendQueue[i].BufLen = 0;
    216 		SendQueue[i].ExtraLen = 0;
    217 
    218 		SendIndex[i] = 0;
    219 	}
    220 
    221 	for (i = 0; i < MaxReceive; i++) {
    222 		ReceiveQueue[i].IsActive = 0;
    223 		ReceiveQueue[i].IsRead = 0;
    224 		ReceiveQueue[i].IsACK = 0;
    225 		ReceiveQueue[i].BufLen = 0;
    226 		ReceiveQueue[i].ExtraLen = 0;
    227 
    228 		ReceiveIndex[i] = 0;
    229 	}
    230 
    231 	//------------------------------------------------------------------------
    232 	//	Init debug values
    233 	//------------------------------------------------------------------------
    234 	DebugOffset = 0;
    235 	DebugSize = 0;
    236 	DebugNames = NULL;
    237 	DebugNameCount = 0;
    238 
    239 }	/* end of Init */
    240 
    241 
    242 /***************************************************************************
    243  * CommBufferClass::Init_Send_Queue -- Clears the send queue               *
    244  *                                                                         *
    245  * INPUT:                                                                  *
    246  *		none.																						*
    247  *                                                                         *
    248  * OUTPUT:                                                                 *
    249  *		none.																						*
    250  *                                                                         *
    251  * WARNINGS:                                                               *
    252  *		none.																						*
    253  *                                                                         *
    254  * HISTORY:                                                                *
    255  *   10/23/1995 BRR : Created.                                             *
    256  *=========================================================================*/
    257 void CommBufferClass::Init_Send_Queue(void)
    258 {
    259 	int i;
    260 
    261 	//------------------------------------------------------------------------
    262 	//	Init data members
    263 	//------------------------------------------------------------------------
    264 	SendCount = 0;
    265 
    266 	//------------------------------------------------------------------------
    267 	//	Init the queue entries
    268 	//------------------------------------------------------------------------
    269 	for (i = 0; i < MaxSend; i++) {
    270 		SendQueue[i].IsActive = 0;
    271 		SendQueue[i].IsACK = 0;
    272 		SendQueue[i].FirstTime = 0L;
    273 		SendQueue[i].LastTime = 0L;
    274 		SendQueue[i].SendCount = 0L;
    275 		SendQueue[i].BufLen = 0;
    276 		SendQueue[i].ExtraLen = 0;
    277 
    278 		SendIndex[i] = 0;
    279 	}
    280 
    281 }	/* end of Init_Send_Queue */
    282 
    283 
    284 /***************************************************************************
    285  * CommBufferClass::Queue_Send -- queues a message for sending             *
    286  *                                                                         *
    287  * INPUT:                                                                  *
    288  *		buf			buffer containing the message										*
    289  *		buflen		length of 'buf'														*
    290  *		extrabuf		buffer containing extra data (optional)						*
    291  *		extralen		length of extra data (optional)									*
    292  *                                                                         *
    293  * OUTPUT:                                                                 *
    294  *		1 = OK, 0 = no room in the queue													*
    295  *                                                                         *
    296  * WARNINGS:                                                               *
    297  *		none.																						*
    298  *                                                                         *
    299  * HISTORY:                                                                *
    300  *   12/20/1994 BR : Created.                                              *
    301  *=========================================================================*/
    302 int CommBufferClass::Queue_Send(void *buf, int buflen, void *extrabuf,
    303 	int extralen)
    304 {
    305 	int i;
    306 	int index;
    307 
    308 	//------------------------------------------------------------------------
    309 	//	Error if no room in the queue
    310 	//------------------------------------------------------------------------
    311 	if (SendCount==MaxSend || buflen > MaxPacketSize)
    312 		return(0);
    313 
    314 	//------------------------------------------------------------------------
    315 	//	Find an empty slot
    316 	//------------------------------------------------------------------------
    317 	index = -1;
    318 	for (i = 0; i < MaxSend; i++) {
    319 		if (SendQueue[i].IsActive==0) {
    320 			index = i;
    321 			break;
    322 		}
    323 	}
    324 	if (index == -1)
    325 		return (0);
    326 
    327 	//------------------------------------------------------------------------
    328 	//	Set entry flags
    329 	//------------------------------------------------------------------------
    330 	SendQueue[index].IsActive = 1;			// entry is now active
    331 	SendQueue[index].IsACK = 0;				// entry hasn't been ACK'd
    332 	SendQueue[index].FirstTime = 0L;			// filled in by Manager when sent
    333 	SendQueue[index].LastTime = 0L;			// filled in by Manager when sent
    334 	SendQueue[index].SendCount = 0L;			// filled in by Manager when sent
    335 	SendQueue[index].BufLen = buflen;		// save buffer size
    336 
    337 	//------------------------------------------------------------------------
    338 	//	Copy the packet data
    339 	//------------------------------------------------------------------------
    340 	memcpy(SendQueue[index].Buffer,buf,buflen);
    341 
    342 	//------------------------------------------------------------------------
    343 	//	Fill in the extra data, if there is any
    344 	//------------------------------------------------------------------------
    345 	if (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {
    346 		memcpy(SendQueue[index].ExtraBuffer,extrabuf,extralen);
    347 		SendQueue[index].ExtraLen = extralen;
    348 	}
    349 	else {
    350 		SendQueue[index].ExtraLen = 0;
    351 	}
    352 
    353 	//------------------------------------------------------------------------
    354 	//	Save this entry's index
    355 	//------------------------------------------------------------------------
    356 	SendIndex[SendCount] = index;
    357 
    358 	//------------------------------------------------------------------------
    359 	//	Increment counters & entry ptr
    360 	//------------------------------------------------------------------------
    361 	SendCount++;
    362 	SendTotal++;
    363 
    364 	return(1);
    365 
    366 }	/* end of Queue_Send */
    367 
    368 
    369 /***************************************************************************
    370  * CommBufferClass::UnQueue_Send -- removes next entry from send queue		*
    371  *                                                                         *
    372  * Frees the given entry; the index given by the caller is the "active"		*
    373  * index value (ie the "nth" active entry), not the actual index in the		*
    374  * array.																						*
    375  *                                                                         *
    376  * INPUT:                                                                  *
    377  *		buf			buffer to store entry's data in; if NULL, it's discarded	*
    378  *		buflen		filled in with length of entry retrieved						*
    379  *		index			"index" of entry to un-queue										*
    380  *		extrabuf		buffer for extra data (optional)									*
    381  *		extralen		ptr to length of extra data (optional)							*
    382  *                                                                         *
    383  * OUTPUT:                                                                 *
    384  *		1 = OK, 0 = no entry to retrieve													*
    385  *                                                                         *
    386  * WARNINGS:                                                               *
    387  *		none.																						*
    388  *                                                                         *
    389  * HISTORY:                                                                *
    390  *   12/20/1994 BR : Created.                                              *
    391  *=========================================================================*/
    392 int CommBufferClass::UnQueue_Send(void *buf, int *buflen, int index,
    393 	void *extrabuf, int *extralen)
    394 {
    395 	int i;
    396 
    397 	//------------------------------------------------------------------------
    398 	//	Error if no entry to retrieve
    399 	//------------------------------------------------------------------------
    400 	if (SendCount==0 || SendQueue[SendIndex[index]].IsActive==0) {
    401 		return(0);
    402 	}
    403 
    404 	//------------------------------------------------------------------------
    405 	//	Copy the data from the entry
    406 	//------------------------------------------------------------------------
    407 	if (buf!=NULL) {
    408 		memcpy(buf,SendQueue[SendIndex[index]].Buffer,
    409 			SendQueue[SendIndex[index]].BufLen);
    410 		(*buflen) = SendQueue[SendIndex[index]].BufLen;
    411 	}
    412 
    413 	//------------------------------------------------------------------------
    414 	//	Copy the extra data
    415 	//------------------------------------------------------------------------
    416 	if (extrabuf!=NULL && extralen!=NULL) {
    417 		memcpy(extrabuf,SendQueue[SendIndex[index]].ExtraBuffer,
    418 			SendQueue[SendIndex[index]].ExtraLen);
    419 		(*extralen) = SendQueue[SendIndex[index]].ExtraLen;
    420 	}
    421 
    422 	//------------------------------------------------------------------------
    423 	//	Set entry flags
    424 	//------------------------------------------------------------------------
    425 	SendQueue[SendIndex[index]].IsActive = 0;
    426 	SendQueue[SendIndex[index]].IsACK = 0;
    427 	SendQueue[SendIndex[index]].FirstTime = 0L;
    428 	SendQueue[SendIndex[index]].LastTime = 0L;
    429 	SendQueue[SendIndex[index]].SendCount = 0L;
    430 	SendQueue[SendIndex[index]].BufLen = 0;
    431 	SendQueue[SendIndex[index]].ExtraLen = 0;
    432 
    433 	//------------------------------------------------------------------------
    434 	//	Move Indices back one
    435 	//------------------------------------------------------------------------
    436 	for (i = index; i < SendCount - 1; i++) {
    437 		SendIndex[i] = SendIndex[i + 1];
    438 	}
    439 	SendIndex[SendCount - 1] = 0;
    440 	SendCount--;
    441 
    442 	return(1);
    443 
    444 }	/* end of UnQueue_Send */
    445 
    446 
    447 /***************************************************************************
    448  * CommBufferClass::Get_Send -- gets ptr to queue entry                    *
    449  *                                                                         *
    450  * This routine gets a pointer to the indicated queue entry.  The index		*
    451  * value is relative to the next-accessible queue entry; 0 = get the			*
    452  * next available queue entry, 1 = get the one behind that, etc.				*
    453  *                                                                         *
    454  * INPUT:                                                                  *
    455  *		index		index of entry to get (0 = 1st available)							*
    456  *                                                                         *
    457  * OUTPUT:                                                                 *
    458  *		ptr to entry																			*
    459  *                                                                         *
    460  * WARNINGS:                                                               *
    461  *		none.																						*
    462  *                                                                         *
    463  * HISTORY:                                                                *
    464  *   12/21/1994 BR : Created.                                              *
    465  *=========================================================================*/
    466 SendQueueType * CommBufferClass::Get_Send(int index)
    467 {
    468 	if (SendQueue[SendIndex[index]].IsActive==0) {
    469 		return(NULL);
    470 	}
    471 	else {
    472 		return(&SendQueue[SendIndex[index]]);
    473 	}
    474 
    475 }	/* end of Get_Send */
    476 
    477 
    478 /***************************************************************************
    479  * CommBufferClass::Queue_Receive -- queues a received message					*
    480  *                                                                         *
    481  * INPUT:                                                                  *
    482  *		buf			buffer containing the message										*
    483  *		buflen		length of 'buf'														*
    484  *		extrabuf		buffer containing extra data (optional)						*
    485  *		extralen		length of extra data (optional)									*
    486  *                                                                         *
    487  * OUTPUT:                                                                 *
    488  *		1 = OK, 0 = no room in the queue													*
    489  *                                                                         *
    490  * WARNINGS:                                                               *
    491  *		none.																						*
    492  *                                                                         *
    493  * HISTORY:                                                                *
    494  *   12/20/1994 BR : Created.                                              *
    495  *=========================================================================*/
    496 int CommBufferClass::Queue_Receive(void *buf, int buflen, void *extrabuf,
    497 	int extralen)
    498 {
    499 	int i;
    500 	int index;
    501 
    502 	//------------------------------------------------------------------------
    503 	//	Error if no room in the queue
    504 	//------------------------------------------------------------------------
    505 	if (ReceiveCount==MaxReceive || buflen > MaxPacketSize) {
    506 		return(0);
    507 	}
    508 
    509 	//------------------------------------------------------------------------
    510 	//	Find an empty slot
    511 	//------------------------------------------------------------------------
    512 	index = -1;
    513 	for (i = 0; i < MaxReceive; i++) {
    514 		if (ReceiveQueue[i].IsActive==0) {
    515 			index = i;
    516 			break;
    517 		}
    518 	}
    519 	if (index == -1)
    520 		return (0);
    521 
    522 	//------------------------------------------------------------------------
    523 	//	Set entry flags
    524 	//------------------------------------------------------------------------
    525 	ReceiveQueue[index].IsActive = 1;
    526 	ReceiveQueue[index].IsRead = 0;
    527 	ReceiveQueue[index].IsACK = 0;
    528 	ReceiveQueue[index].BufLen = buflen;
    529 
    530 	//------------------------------------------------------------------------
    531 	//	Copy the packet data
    532 	//------------------------------------------------------------------------
    533 	memcpy(ReceiveQueue[index].Buffer,buf,buflen);
    534 
    535 	//------------------------------------------------------------------------
    536 	//	Fill in the extra data, if there is any
    537 	//------------------------------------------------------------------------
    538 	if (extrabuf!=NULL && extralen > 0 && extralen <= MaxExtraSize) {
    539 		memcpy(ReceiveQueue[index].ExtraBuffer,extrabuf,extralen);
    540 		ReceiveQueue[index].ExtraLen = extralen;
    541 	}
    542 	else {
    543 		ReceiveQueue[index].ExtraLen = 0;
    544 	}
    545 
    546 	//------------------------------------------------------------------------
    547 	//	Save this entry's index
    548 	//------------------------------------------------------------------------
    549 	ReceiveIndex[ReceiveCount] = index;
    550 
    551 	//------------------------------------------------------------------------
    552 	//	Increment counters & entry ptr
    553 	//------------------------------------------------------------------------
    554 	ReceiveCount++;
    555 	ReceiveTotal++;
    556 
    557 	return(1);
    558 
    559 }	/* end of Queue_Receive */
    560 
    561 
    562 /***************************************************************************
    563  * CommBufferClass::UnQueue_Receive -- removes next entry from send queue	*
    564  *                                                                         *
    565  * Frees the given entry; the index given by the caller is the "active"		*
    566  * index value (ie the "nth" active entry), not the actual index in the		*
    567  * array.																						*
    568  *                                                                         *
    569  * INPUT:                                                                  *
    570  *		buf			buffer to store entry's data in; if NULL, it's discarded	*
    571  *		buflen		filled in with length of entry retrieved						*
    572  *		index			index of entry to un-queue											*
    573  *		extrabuf		buffer for extra data (optional)									*
    574  *		extralen		ptr to length of extra data (optional)							*
    575  *                                                                         *
    576  * OUTPUT:                                                                 *
    577  *		1 = OK, 0 = no entry to retrieve													*
    578  *                                                                         *
    579  * WARNINGS:                                                               *
    580  *		none.																						*
    581  *                                                                         *
    582  * HISTORY:                                                                *
    583  *   12/20/1994 BR : Created.                                              *
    584  *=========================================================================*/
    585 int CommBufferClass::UnQueue_Receive(void *buf, int *buflen, int index,
    586 	void *extrabuf, int *extralen)
    587 {
    588 	int i;
    589 
    590 	//------------------------------------------------------------------------
    591 	//	Error if no entry to retrieve
    592 	//------------------------------------------------------------------------
    593 	if (ReceiveCount==0 || ReceiveQueue[ReceiveIndex[index]].IsActive==0) {
    594 		return(0);
    595 	}
    596 
    597 	//------------------------------------------------------------------------
    598 	//	Copy the data from the entry
    599 	//------------------------------------------------------------------------
    600 	if (buf!=NULL) {
    601 		memcpy(buf,ReceiveQueue[ReceiveIndex[index]].Buffer,
    602 			ReceiveQueue[ReceiveIndex[index]].BufLen);
    603 		(*buflen) = ReceiveQueue[ReceiveIndex[index]].BufLen;
    604 	}
    605 
    606 	//------------------------------------------------------------------------
    607 	//	Copy the extra data
    608 	//------------------------------------------------------------------------
    609 	if (extrabuf!=NULL && extralen!=NULL) {
    610 		memcpy(extrabuf,ReceiveQueue[ReceiveIndex[index]].ExtraBuffer,
    611 			ReceiveQueue[ReceiveIndex[index]].ExtraLen);
    612 		(*extralen) = ReceiveQueue[ReceiveIndex[index]].ExtraLen;
    613 	}
    614 
    615 	//------------------------------------------------------------------------
    616 	//	Set entry flags
    617 	//------------------------------------------------------------------------
    618 	ReceiveQueue[ReceiveIndex[index]].IsActive = 0;
    619 	ReceiveQueue[ReceiveIndex[index]].IsRead = 0;
    620 	ReceiveQueue[ReceiveIndex[index]].IsACK = 0;
    621 	ReceiveQueue[ReceiveIndex[index]].BufLen = 0;
    622 	ReceiveQueue[ReceiveIndex[index]].ExtraLen = 0;
    623 
    624 	//------------------------------------------------------------------------
    625 	//	Move Indices back one
    626 	//------------------------------------------------------------------------
    627 	for (i = index; i < ReceiveCount - 1; i++) {
    628 		ReceiveIndex[i] = ReceiveIndex[i + 1];
    629 	}
    630 	ReceiveIndex[ReceiveCount - 1] = 0;
    631 	ReceiveCount--;
    632 
    633 	return(1);
    634 
    635 }	/* end of UnQueue_Receive */
    636 
    637 
    638 /***************************************************************************
    639  * CommBufferClass::Get_Receive -- gets ptr to queue entry                 *
    640  *                                                                         *
    641  * This routine gets a pointer to the indicated queue entry.  The index		*
    642  * value is relative to the next-accessible queue entry; 0 = get the			*
    643  * next available queue entry, 1 = get the one behind that, etc.				*
    644  *                                                                         *
    645  * INPUT:                                                                  *
    646  *		index		index of entry to get (0 = 1st available)							*
    647  *                                                                         *
    648  * OUTPUT:                                                                 *
    649  *		ptr to entry																			*
    650  *                                                                         *
    651  * WARNINGS:                                                               *
    652  *		none.																						*
    653  *                                                                         *
    654  * HISTORY:                                                                *
    655  *   12/21/1994 BR : Created.                                              *
    656  *=========================================================================*/
    657 ReceiveQueueType * CommBufferClass::Get_Receive(int index)
    658 {
    659 	if (ReceiveQueue[ReceiveIndex[index]].IsActive==0) {
    660 		return(NULL);
    661 	}
    662 	else {
    663 		return(&ReceiveQueue[ReceiveIndex[index]]);
    664 	}
    665 
    666 }	/* end of Get_Receive */
    667 
    668 
    669 /***************************************************************************
    670  * CommBufferClass::Add_Delay -- adds a new delay value for response time  *
    671  *                                                                         *
    672  * This routine updates the average response time for this queue.  The		*
    673  * computation is based on the average of the last 'n' delay values given,	*
    674  * It computes a running total of the last n delay values, then divides 	*
    675  * that by n to compute the average.													*
    676  *																									*
    677  * When the number of values given exceeds the max, the mean is subtracted	*
    678  * off the total, then the new value is added in.  Thus, any single delay	*
    679  * value will have an effect on the total that approaches 0 over time, and	*
    680  * the new delay value contributes to 1/n of the mean.							*
    681  *                                                                         *
    682  * INPUT:                                                                  *
    683  *		delay			value to add into the response time computation				*
    684  *                                                                         *
    685  * OUTPUT:                                                                 *
    686  *		none.																						*
    687  *                                                                         *
    688  * WARNINGS:                                                               *
    689  *		none.																						*
    690  *                                                                         *
    691  * HISTORY:                                                                *
    692  *   01/19/1995 BR : Created.                                              *
    693  *=========================================================================*/
    694 void CommBufferClass::Add_Delay(unsigned long delay)
    695 {
    696 	int roundoff = 0;
    697 
    698 	if (NumDelay==256) {
    699 		DelaySum -= MeanDelay;
    700 		DelaySum += delay;
    701 		if ( (DelaySum & 0x00ff) > 127)
    702 			roundoff = 1;
    703 		MeanDelay = (DelaySum >> 8) + roundoff;
    704 	}
    705 	else {
    706 		NumDelay++;
    707 		DelaySum += delay;
    708 		MeanDelay = DelaySum / NumDelay;
    709 	}
    710 
    711 	if (delay > MaxDelay) {
    712 		MaxDelay = delay;
    713 	}
    714 
    715 }	/* end of Add_Delay */
    716 
    717 
    718 /***************************************************************************
    719  * CommBufferClass::Avg_Response_Time -- returns average response time    	*
    720  *                                                                         *
    721  * INPUT:                                                                  *
    722  *		none.																						*
    723  *                                                                         *
    724  * OUTPUT:                                                                 *
    725  *		latest computed average response time											*
    726  *                                                                         *
    727  * WARNINGS:                                                               *
    728  *		none.																						*
    729  *                                                                         *
    730  * HISTORY:                                                                *
    731  *   01/19/1995 BR : Created.                                              *
    732  *=========================================================================*/
    733 unsigned long CommBufferClass::Avg_Response_Time(void)
    734 {
    735 	return(MeanDelay);
    736 
    737 }	/* end of Avg_Response_Time */
    738 
    739 
    740 /***************************************************************************
    741  * CommBufferClass::Max_Response_Time -- returns max response time    		*
    742  *                                                                         *
    743  * INPUT:                                                                  *
    744  *		none.																						*
    745  *                                                                         *
    746  * OUTPUT:                                                                 *
    747  *		latest computed average response time											*
    748  *                                                                         *
    749  * WARNINGS:                                                               *
    750  *		none.																						*
    751  *                                                                         *
    752  * HISTORY:                                                                *
    753  *   01/19/1995 BR : Created.                                              *
    754  *=========================================================================*/
    755 unsigned long CommBufferClass::Max_Response_Time(void)
    756 {
    757 	return(MaxDelay);
    758 
    759 }	/* end of Max_Response_Time */
    760 
    761 
    762 /***************************************************************************
    763  * CommBufferClass::Reset_Response_Time -- resets computations					*
    764  *                                                                         *
    765  * INPUT:                                                                  *
    766  *		none.																						*
    767  *                                                                         *
    768  * OUTPUT:                                                                 *
    769  *		none.																						*
    770  *                                                                         *
    771  * WARNINGS:                                                               *
    772  *		none.																						*
    773  *                                                                         *
    774  * HISTORY:                                                                *
    775  *   01/19/1995 BR : Created.                                              *
    776  *=========================================================================*/
    777 void CommBufferClass::Reset_Response_Time(void)
    778 {
    779 	DelaySum = 0L;
    780 	NumDelay = 0L;
    781 	MeanDelay = 0L;
    782 	MaxDelay = 0L;
    783 
    784 }	/* end of Reset_Response_Time */
    785 
    786 
    787 /***************************************************************************
    788  * CommBufferClass::Configure_Debug -- sets up special debug values        *
    789  *                                                                         *
    790  * Mono_Debug_Print2() can look into a packet to pull out a particular		*
    791  * ID, and can print both that ID and a string corresponding to				*
    792  * that ID.  This routine configures these values so it can find				*
    793  * and decode the ID.  This ID is used in addition to the normal				*
    794  * CommHeaderType values.																	*
    795  *                                                                         *
    796  * INPUT:                                                                  *
    797  *		type_offset		ID's byte offset into packet									*
    798  *		type_size		size of ID, in bytes; 0 if none								*
    799  *		names				ptr to array of names; use ID as an index into this	*
    800  *		maxnames			max # in the names array; 0 if none.						*
    801  *                                                                         *
    802  * OUTPUT:                                                                 *
    803  *		none.																						*
    804  *                                                                         *
    805  * WARNINGS:                                                               *
    806  *		Names shouldn't be longer than 12 characters.								*
    807  *                                                                         *
    808  * HISTORY:                                                                *
    809  *   05/31/1995 BRR : Created.                                             *
    810  *=========================================================================*/
    811 void CommBufferClass::Configure_Debug(int type_offset, int type_size,
    812 	char **names, int namestart, int namecount)
    813 {
    814 	DebugOffset = type_offset;
    815 	DebugSize = type_size;
    816 	DebugNames = names;
    817 	DebugNameStart = namestart;
    818 	DebugNameCount = namecount;
    819 
    820 }	/* end of Configure_Debug */
    821 
    822 
    823 /***************************************************************************
    824  * Mono_Debug_Print -- Debug output routine                                *
    825  *                                                                         *
    826  * This routine leaves 5 lines at the top for the caller's use.				*
    827  *                                                                         *
    828  * INPUT:                                                                  *
    829  *		refresh		1 = clear screen & completely refresh							*
    830  *                                                                         *
    831  * OUTPUT:                                                                 *
    832  *		none.																						*
    833  *                                                                         *
    834  * WARNINGS:                                                               *
    835  *		none.																						*
    836  *                                                                         *
    837  * HISTORY:                                                                *
    838  *   05/02/1995 BRR : Created.                                             *
    839  *=========================================================================*/
    840 void CommBufferClass::Mono_Debug_Print(int refresh)
    841 {
    842 #ifdef WWLIB32_H
    843 	int i;												// loop counter
    844 	static int send_col[] = {1,14,28};			// coords of send queue columns
    845 	static int receive_col[] = {40,54,68};		// coords of recv queue columns
    846 	int row,col;										// current row,col for printing
    847 	int num;												// max # items to print
    848 
    849 	struct CommHdr {									// this mirrors the CommHeaderType
    850 		unsigned short MagicNumber;
    851 		unsigned char Code;
    852 		unsigned long PacketID;
    853 	} *hdr;
    854 
    855 	//------------------------------------------------------------------------
    856 	//	If few enough entries, call the verbose debug version
    857 	//------------------------------------------------------------------------
    858 	if (MaxSend <= 16) {
    859 		Mono_Debug_Print2(refresh);
    860 		return;
    861 	}
    862 
    863 	//------------------------------------------------------------------------
    864 	//	Refresh the screen
    865 	//------------------------------------------------------------------------
    866 	if (refresh) {
    867 		Mono_Clear_Screen ();
    868 		Mono_Printf("ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n");
    869 		Mono_Printf("³                                                                             ³\n");
    870 		Mono_Printf("³                                                                             ³\n");
    871 		Mono_Printf("³                                                                             ³\n");
    872 		Mono_Printf("ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\n");
    873 		Mono_Printf("³              Send Queue              ³             Receive Queue            ³\n");
    874 		Mono_Printf("³                                      ³                                      ³\n");
    875 		Mono_Printf("³ ID  Ct ACK   ID  Ct ACK    ID  Ct ACK³ ID  Rd ACK    ID  Rd ACK   ID  Rd ACK³\n");
    876 		Mono_Printf("³                                      ³                                      ³\n");
    877 		Mono_Printf("³                                      ³                                      ³\n");
    878 		Mono_Printf("³                                      ³                                      ³\n");
    879 		Mono_Printf("³                                      ³                                      ³\n");
    880 		Mono_Printf("³                                      ³                                      ³\n");
    881 		Mono_Printf("³                                      ³                                      ³\n");
    882 		Mono_Printf("³                                      ³                                      ³\n");
    883 		Mono_Printf("³                                      ³                                      ³\n");
    884 		Mono_Printf("³                                      ³                                      ³\n");
    885 		Mono_Printf("³                                      ³                                      ³\n");
    886 		Mono_Printf("³                                      ³                                      ³\n");
    887 		Mono_Printf("³                                      ³                                      ³\n");
    888 		Mono_Printf("³                                      ³                                      ³\n");
    889 		Mono_Printf("³                                      ³                                      ³\n");
    890 		Mono_Printf("³                                      ³                                      ³\n");
    891 		Mono_Printf("³                                      ³                                      ³\n");
    892 		Mono_Printf("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
    893 	}
    894 
    895 	//------------------------------------------------------------------------
    896 	//	Print Send Queue items
    897 	//------------------------------------------------------------------------
    898 	if (MaxSend <= 48) {
    899 		num = MaxSend;
    900 	}
    901 	else {
    902 		num = 48;
    903 	}
    904 	col = 0;
    905 	row = 0;
    906 	for (i = 0; i < MaxSend; i++) {
    907 		Mono_Set_Cursor (send_col[col],row + 8);
    908 		if (SendQueue[i].IsActive) {
    909 			hdr = (CommHdr *)SendQueue[i].Buffer;
    910 			hdr->MagicNumber = hdr->MagicNumber;
    911 			hdr->Code = hdr->Code;
    912 			Mono_Printf ("%4d %2d  %d",hdr->PacketID, SendQueue[i].SendCount,
    913 				SendQueue[i].IsACK);
    914 		}
    915 		else {
    916 			Mono_Printf ("____ __  _ ");
    917 		}
    918 
    919 		row++;
    920 		if (row > 15) {
    921 			row = 0;
    922 			col++;
    923 		}
    924 	}
    925 
    926 	//------------------------------------------------------------------------
    927 	//	Print Receive Queue items
    928 	//------------------------------------------------------------------------
    929 	if (MaxReceive <= 48) {
    930 		num = MaxSend;
    931 	}
    932 	else {
    933 		num = 48;
    934 	}
    935 	col = 0;
    936 	row = 0;
    937 	for (i = 0; i < MaxReceive; i++) {
    938 		Mono_Set_Cursor (receive_col[col],row + 8);
    939 		if (ReceiveQueue[i].IsActive) {
    940 			hdr = (CommHdr *)ReceiveQueue[i].Buffer;
    941 			Mono_Printf ("%4d  %d  %d",hdr->PacketID, ReceiveQueue[i].IsRead,
    942 				ReceiveQueue[i].IsACK);
    943 		}
    944 		else {
    945 			Mono_Printf ("____  _  _ ");
    946 		}
    947 
    948 		row++;
    949 		if (row > 15) {
    950 			row = 0;
    951 			col++;
    952 		}
    953 	}
    954 
    955 #else
    956 	refresh = refresh;
    957 #endif
    958 }	/* end of Mono_Debug_Print */
    959 
    960 
    961 /***************************************************************************
    962  * CommBufferClass::Mono_Debug_Print2 -- Debug output; alternate format    *
    963  *                                                                         *
    964  * This routine prints more information than the other version; it's			*
    965  * called only if the number of queue entries is small enough to support	*
    966  * this format.																				*
    967  *                                                                         *
    968  * INPUT:                                                                  *
    969  *		refresh		1 = clear screen & completely refresh							*
    970  *                                                                         *
    971  * OUTPUT:                                                                 *
    972  *		none.																						*
    973  *                                                                         *
    974  * WARNINGS:                                                               *
    975  *		none.																						*
    976  *                                                                         *
    977  * HISTORY:                                                                *
    978  *   05/31/1995 BRR : Created.                                             *
    979  *=========================================================================*/
    980 void CommBufferClass::Mono_Debug_Print2(int refresh)
    981 {
    982 #ifdef WWLIB32_H
    983 	int i;												// loop counter
    984 	char txt[80];
    985 	int val;
    986 
    987 	struct CommHdr {									// this mirrors the CommHeaderType
    988 		unsigned short MagicNumber;
    989 		unsigned char Code;
    990 		unsigned long PacketID;
    991 	} *hdr;
    992 
    993 	//------------------------------------------------------------------------
    994 	//	Refresh the screen
    995 	//------------------------------------------------------------------------
    996 	if (refresh) {
    997 		Mono_Clear_Screen ();
    998 		Mono_Printf("ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n");
    999 		Mono_Printf("³                                                                             ³\n");
   1000 		Mono_Printf("³                                                                             ³\n");
   1001 		Mono_Printf("³                                                                             ³\n");
   1002 		Mono_Printf("ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\n");
   1003 		Mono_Printf("³              Send Queue              ³             Receive Queue            ³\n");
   1004 		Mono_Printf("³                                      ³                                      ³\n");
   1005 		Mono_Printf("³ ID  Ct Type   Data  Name         ACK ³ ID  Rd Type   Data  Name         ACK ³\n");
   1006 		Mono_Printf("³                                      ³                                      ³\n");
   1007 		Mono_Printf("³                                      ³                                      ³\n");
   1008 		Mono_Printf("³                                      ³                                      ³\n");
   1009 		Mono_Printf("³                                      ³                                      ³\n");
   1010 		Mono_Printf("³                                      ³                                      ³\n");
   1011 		Mono_Printf("³                                      ³                                      ³\n");
   1012 		Mono_Printf("³                                      ³                                      ³\n");
   1013 		Mono_Printf("³                                      ³                                      ³\n");
   1014 		Mono_Printf("³                                      ³                                      ³\n");
   1015 		Mono_Printf("³                                      ³                                      ³\n");
   1016 		Mono_Printf("³                                      ³                                      ³\n");
   1017 		Mono_Printf("³                                      ³                                      ³\n");
   1018 		Mono_Printf("³                                      ³                                      ³\n");
   1019 		Mono_Printf("³                                      ³                                      ³\n");
   1020 		Mono_Printf("³                                      ³                                      ³\n");
   1021 		Mono_Printf("³                                      ³                                      ³\n");
   1022 		Mono_Printf("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
   1023 	}
   1024 
   1025 	//------------------------------------------------------------------------
   1026 	//	Print Send Queue items
   1027 	//------------------------------------------------------------------------
   1028 	for (i = 0; i < MaxSend; i++) {
   1029 		Mono_Set_Cursor (1,8 + i);
   1030 
   1031 		//.....................................................................
   1032 		//	Print an active entry
   1033 		//.....................................................................
   1034 		if (SendQueue[i].IsActive) {
   1035 
   1036 			//..................................................................
   1037 			//	Get header info
   1038 			//..................................................................
   1039 			hdr = (CommHdr *)SendQueue[i].Buffer;
   1040 			hdr->MagicNumber = hdr->MagicNumber;
   1041 			hdr->Code = hdr->Code;
   1042 			sprintf(txt,"%4d %2d %-5s  ",
   1043 				hdr->PacketID,
   1044 				SendQueue[i].SendCount,
   1045 				ConnectionClass::Command_Name(hdr->Code));
   1046 
   1047 			//..................................................................
   1048 			//	Decode app's ID & its name
   1049 			//..................................................................
   1050 			if (DebugSize && (DebugOffset + DebugSize) <= SendQueue[i].BufLen) {
   1051 				if (DebugSize==1) {
   1052 					val = *(SendQueue[i].Buffer + DebugOffset);
   1053 
   1054 				}
   1055 				else if (DebugSize==2) {
   1056 					val = *((short *)(SendQueue[i].Buffer + DebugOffset));
   1057 
   1058 				}
   1059 				else if (DebugSize==4) {
   1060 					val = *((int *)(SendQueue[i].Buffer + DebugOffset));
   1061 				}
   1062 				sprintf(txt + strlen(txt),"%4d  ",val);
   1063 
   1064 				if (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {
   1065 					sprintf(txt + strlen(txt),"%-12s  %x",
   1066 						DebugNames[val - DebugNameStart], SendQueue[i].IsACK);
   1067 				}
   1068 				else {
   1069 					sprintf(txt + strlen(txt),"              %x",
   1070 						SendQueue[i].IsACK);
   1071 				}
   1072 			}
   1073 			else {
   1074 				sprintf(txt + strlen(txt),"                    %x",
   1075 					SendQueue[i].IsACK);
   1076 			}
   1077 
   1078 			Mono_Printf("%s",txt);
   1079 		}
   1080 		else {
   1081 
   1082 			//..................................................................
   1083 			//	Entry isn't active; print blanks
   1084 			//..................................................................
   1085 			Mono_Printf("____ __                            _");
   1086 		}
   1087 	}
   1088 
   1089 	//------------------------------------------------------------------------
   1090 	//	Print Receive Queue items
   1091 	//------------------------------------------------------------------------
   1092 	for (i = 0; i < MaxReceive; i++) {
   1093 		Mono_Set_Cursor (40,8 + i);
   1094 
   1095 		//.....................................................................
   1096 		//	Print an active entry
   1097 		//.....................................................................
   1098 		if (ReceiveQueue[i].IsActive) {
   1099 
   1100 			//..................................................................
   1101 			//	Get header info
   1102 			//..................................................................
   1103 			hdr = (CommHdr *)ReceiveQueue[i].Buffer;
   1104 			hdr->MagicNumber = hdr->MagicNumber;
   1105 			hdr->Code = hdr->Code;
   1106 			sprintf(txt,"%4d %2d %-5s  ",
   1107 				hdr->PacketID,
   1108 				ReceiveQueue[i].IsRead,
   1109 				ConnectionClass::Command_Name(hdr->Code));
   1110 
   1111 			//..................................................................
   1112 			//	Decode app's ID & its name
   1113 			//..................................................................
   1114 			if (DebugSize && (DebugOffset + DebugSize) <= ReceiveQueue[i].BufLen) {
   1115 				if (DebugSize==1) {
   1116 					val = *(ReceiveQueue[i].Buffer + DebugOffset);
   1117 
   1118 				}
   1119 				else if (DebugSize==2) {
   1120 					val = *((short *)(ReceiveQueue[i].Buffer + DebugOffset));
   1121 
   1122 				}
   1123 				else if (DebugSize==4) {
   1124 					val = *((int *)(ReceiveQueue[i].Buffer + DebugOffset));
   1125 				}
   1126 				sprintf(txt + strlen(txt),"%4d  ",val);
   1127 
   1128 				if (DebugNameCount > 0 && val >= 0 && val < DebugNameCount) {
   1129 					sprintf(txt + strlen(txt),"%-12s  %x",
   1130 						DebugNames[val - DebugNameStart], ReceiveQueue[i].IsACK);
   1131 				}
   1132 				else {
   1133 					sprintf(txt + strlen(txt),"              %x",
   1134 						ReceiveQueue[i].IsACK);
   1135 				}
   1136 			}
   1137 			else {
   1138 				sprintf(txt + strlen(txt),"                    %x",
   1139 					ReceiveQueue[i].IsACK);
   1140 			}
   1141 
   1142 			Mono_Printf("%s",txt);
   1143 		}
   1144 		else {
   1145 
   1146 			//..................................................................
   1147 			//	Entry isn't active; print blanks
   1148 			//..................................................................
   1149 			Mono_Printf("____ __                            _");
   1150 		}
   1151 	}
   1152 
   1153 #else
   1154 	refresh = refresh;
   1155 #endif
   1156 }	/* end of Mono_Debug_Print2 */
   1157 
   1158 
   1159 /************************** end of combuf.cpp ******************************/
   1160 
   1161