CnC_Remastered_Collection

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

IPXMGR.CPP (81680B)


      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:   F:\projects\c&c\vcs\code\ipxmgr.cpv   1.9   16 Oct 1995 16:48:22   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 : IPXMGR.CPP                               *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : December 20, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : May 4, 1995 [BRR]                        *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Functions:                                                       			*
     33  *   IPXManagerClass::IPXManagerClass -- class constructor                 *
     34  *   IPXManagerClass::~IPXManagerClass -- class destructor                 *
     35  *   IPXManagerClass::Init -- initialization routine								*
     36  *   IPXManagerClass::Is_IPX -- tells if IPX is installed or not				*
     37  *   IPXManagerClass::Set_Timing -- sets timing for all connections			*
     38  *   IPXManagerClass::Create_Connection -- creates a new connection        *
     39  *   IPXManagerClass::Delete_Connection -- deletes a connection            *
     40  *   IPXManagerClass::Num_Connections -- gets the # of connections			*
     41  *   IPXManagerClass::Connection_ID -- gets the given connection's ID      *
     42  *   IPXManagerClass::Connection_Name -- gets name for given connection    *
     43  *   IPXManagerClass::Connection_Address -- retrieves connection's address	*
     44  *   IPXManagerClass::Connection_Index -- gets given connection's index    *
     45  *   IPXManagerClass::Send_Global_Message -- sends a Global Message			*
     46  *   IPXManagerClass::Get_Global_Message -- polls the Global Message queue	*
     47  *   IPXManagerClass::Send_Private_Message -- Sends a Private Message		*
     48  *   IPXManagerClass::Get_Private_Message -- Polls Private Message queue	*
     49  *   IPXManagerClass::Service -- main polling routine for IPX Connections	*
     50  *   IPXManagerClass::Get_Bad_Connection -- returns bad connection ID      *
     51  *   IPXManagerClass::Global_Num_Send	-- gets # entries in send queue	   *
     52  *   IPXManagerClass::Global_Num_Receive -- gets # entries in recv queue   *
     53  *   IPXManagerClass::Private_Num_Send -- gets # entries in send queue	   *
     54  *   IPXManagerClass::Private_Num_Receive -- gets # entries in recv queue  *
     55  *   IPXManagerClass::Set_Bridge -- prepares to cross a bridge             *
     56  *   IPXManagerClass::Set_Socket -- sets socket ID for all connections		*
     57  *   IPXManagerClass::Response_Time -- Returns largest Avg Response Time   *
     58  *   IPXManagerClass::Global_Response_Time -- Returns Avg Response Time    *
     59  *   IPXManagerClass::Reset_Response_Time -- Reset response time 				*
     60  *   IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf           *
     61  *   IPXManagerClass::Mono_Debug_Print -- debug output routine					*
     62  *   IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory		*
     63  *   IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory				*
     64  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     65 
     66 #include "function.h"
     67 #include "ipx95.h"
     68 #include "tcpip.h"
     69 
     70 /***************************************************************************
     71  * IPXManagerClass::IPXManagerClass -- class constructor                   *
     72  *                                                                         *
     73  * INPUT:                                                                  *
     74  *		glb_maxlen		Global Channel maximum packet length						*
     75  *		pvt_maxlen		Private Channel maximum packet length						*
     76  *		socket			socket ID to use													*
     77  *		product_id		a unique numerical ID for this product						*
     78  *                                                                         *
     79  * OUTPUT:                                                                 *
     80  *		none.																						*
     81  *                                                                         *
     82  * WARNINGS:                                                               *
     83  *		The socket number is byte-swapped, since IPX requires socket ID's		*
     84  *		to be stored high/low.																*
     85  *                                                                         *
     86  * HISTORY:                                                                *
     87  *   12/20/1994 BR : Created.                                              *
     88  *=========================================================================*/
     89 IPXManagerClass::IPXManagerClass (int glb_maxlen, int pvt_maxlen,
     90 	int glb_num_packets, int pvt_num_packets, unsigned short socket,
     91 	unsigned short product_id)
     92 {
     93 	int i;
     94 
     95 	/*------------------------------------------------------------------------
     96 	Initialize data members
     97 	------------------------------------------------------------------------*/
     98 	/*........................................................................
     99 	IPXStatus = 1 if IPX is installed, 0 if not
    100 	........................................................................*/
    101 	if (IPX_SPX_Installed()==0) {
    102 		IPXStatus = 0;
    103 	} else {
    104 		IPXStatus = 1;
    105 	}
    106 
    107 	/*........................................................................
    108 	Set listening state flag to off
    109 	........................................................................*/
    110 	Listening = 0;
    111 
    112 	/*........................................................................
    113 	No memory has been alloc'd yet
    114 	........................................................................*/
    115 	RealMemAllocd = 0;
    116 
    117 	/*........................................................................
    118 	Set max packet sizes, for allocating real-mode memory
    119 	........................................................................*/
    120 	Glb_MaxPacketLen = glb_maxlen;
    121 	Glb_NumPackets = glb_num_packets;
    122 	Pvt_MaxPacketLen = pvt_maxlen;
    123 	Pvt_NumPackets = pvt_num_packets;
    124 
    125 	/*........................................................................
    126 	Save the app's product ID
    127 	........................................................................*/
    128 	ProductID = product_id;
    129 
    130 	/*........................................................................
    131 	Save our socket ID number
    132 	........................................................................*/
    133 	Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |
    134 		(((unsigned long)socket & 0xff00) >> 8));
    135 
    136 	/*........................................................................
    137 	Get the user's IPX local connection number
    138 	........................................................................*/
    139 	if (IPXStatus) {
    140 		ConnectionNum = IPX_Get_Connection_Number();
    141 	} else {
    142 		ConnectionNum = 0;
    143 	}
    144 
    145 	/*........................................................................
    146 	Init connection states
    147 	........................................................................*/
    148 	NumConnections = 0;
    149 	CurConnection = 0;
    150 	for (i = 0; i < CONNECT_MAX; i++)
    151 		Connection[i] = 0;
    152 	GlobalChannel = 0;
    153 
    154 	SendOverflows = 0;
    155 	ReceiveOverflows = 0;
    156 	BadConnection = IPXConnClass::CONNECTION_NONE;
    157 
    158 	/*........................................................................
    159 	Init timing parameters
    160 	........................................................................*/
    161 	RetryDelta = 2;		// 2 ticks between retries
    162 	MaxRetries = -1;		// disregard # retries
    163 	Timeout = 60;			// report bad connection after 1 second
    164 
    165 }	/* end of IPXManagerClass */
    166 
    167 
    168 /***************************************************************************
    169  * IPXManagerClass::~IPXManagerClass -- class destructor                   *
    170  *                                                                         *
    171  * INPUT:                                                                  *
    172  *		none.																						*
    173  *                                                                         *
    174  * OUTPUT:                                                                 *
    175  *		none.																						*
    176  *                                                                         *
    177  * WARNINGS:                                                               *
    178  *		none.																						*
    179  *                                                                         *
    180  * HISTORY:                                                                *
    181  *   12/20/1994 BR : Created.                                              *
    182  *=========================================================================*/
    183 IPXManagerClass::~IPXManagerClass()
    184 {
    185 	int i;
    186 
    187 	/*------------------------------------------------------------------------
    188 	Stop all IPX events
    189 	------------------------------------------------------------------------*/
    190 	if (Listening) {
    191 		IPXConnClass::Stop_Listening();
    192 		Listening = 0;
    193 	}
    194 
    195 	/*------------------------------------------------------------------------
    196 	Free all protected-mode memory
    197 	------------------------------------------------------------------------*/
    198 	if (GlobalChannel) {
    199 		delete GlobalChannel;
    200 		GlobalChannel = 0;
    201 	}
    202 	for (i = 0; i < NumConnections; i++) {
    203 		delete Connection[i];
    204 		Connection[i] = 0;
    205 	}
    206 	NumConnections = 0;
    207 
    208 	/*------------------------------------------------------------------------
    209 	Free all real-mode memory
    210 	------------------------------------------------------------------------*/
    211 	if (RealMemAllocd) {
    212 		Free_RealMode_Mem();
    213 		RealMemAllocd = 0;
    214 	}
    215 
    216 }	/* end of ~IPXManagerClass */
    217 
    218 
    219 /***************************************************************************
    220  * IPXManagerClass::Init -- initialization routine									*
    221  *                                                                         *
    222  * This routine allocates memory,
    223  *                                                                         *
    224  * INPUT:                                                                  *
    225  *		none.																						*
    226  *                                                                         *
    227  * OUTPUT:                                                                 *
    228  *		1 = OK, 0 = error																		*
    229  *                                                                         *
    230  * WARNINGS:                                                               *
    231  *		none.																						*
    232  *                                                                         *
    233  * HISTORY:                                                                *
    234  *   12/20/1994 BR : Created.                                              *
    235  *=========================================================================*/
    236 int IPXManagerClass::Init()
    237 {
    238 	int i;
    239 
    240 	if (!(GameToPlay == GAME_INTERNET)){
    241 		/*
    242 		----------------------- Error if IPX not installed -----------------------
    243 		*/
    244 		if (!IPXStatus) {
    245 			return(false);
    246 		}
    247 
    248 		/*------------------------------------------------------------------------
    249 		Stop Listening
    250 		------------------------------------------------------------------------*/
    251 		if (Listening) {
    252 			IPXConnClass::Stop_Listening();
    253 			Listening = 0;
    254 		}
    255 
    256 		/*------------------------------------------------------------------------
    257 		Free Real-mode memory
    258 		------------------------------------------------------------------------*/
    259 		if (RealMemAllocd) {
    260 			Free_RealMode_Mem();
    261 			RealMemAllocd = 0;
    262 		}
    263 	}else{
    264 		/*
    265 		** Pretend IPX is available for Internet games whether it is or not
    266 		*/
    267 		IPXStatus = 1;
    268 	}
    269 
    270 	/*------------------------------------------------------------------------
    271 	Free protected-mode memory
    272 	------------------------------------------------------------------------*/
    273 	if (GlobalChannel) {
    274 		delete GlobalChannel;
    275 		GlobalChannel = 0;
    276 	}
    277 	for (i = 0; i < NumConnections; i++) {
    278 		delete Connection[i];
    279 		Connection[i] = 0;
    280 	}
    281 	NumConnections = 0;
    282 
    283 
    284 	if (!(GameToPlay == GAME_INTERNET)){
    285 		/*------------------------------------------------------------------------
    286 		Allocate real-mode memory
    287 		------------------------------------------------------------------------*/
    288 		if (!Alloc_RealMode_Mem()) return(false);
    289 		RealMemAllocd = 1;
    290 	}
    291 
    292 	/*------------------------------------------------------------------------
    293 	Allocate the Global Channel
    294 	------------------------------------------------------------------------*/
    295 	GlobalChannel = new IPXGlobalConnClass (Glb_NumPackets, Glb_NumPackets,
    296 		Glb_MaxPacketLen, ProductID);
    297 	if (!GlobalChannel)
    298 		return(false);
    299 	GlobalChannel->Init();
    300 	GlobalChannel->Set_Retry_Delta (RetryDelta);
    301 	GlobalChannel->Set_Max_Retries (MaxRetries);
    302 	GlobalChannel->Set_TimeOut (Timeout);
    303 
    304 	/*------------------------------------------------------------------------
    305 	Configure the IPX Connections
    306 	------------------------------------------------------------------------*/
    307 	IPXConnClass::Configure(Socket, ConnectionNum, ListenECB, SendECB,
    308 		FirstHeaderBuf, SendHeader, FirstDataBuf, SendBuf, Handler, PacketLen);
    309 
    310 	/*------------------------------------------------------------------------
    311 	Start Listening
    312 	------------------------------------------------------------------------*/
    313 	if (!(GameToPlay == GAME_INTERNET)){
    314 		if (!IPXConnClass::Start_Listening()) return(false);
    315 	}
    316 
    317 	Listening = 1;
    318 
    319 	return(true);
    320 }
    321 
    322 
    323 /***************************************************************************
    324  * IPXManagerClass::Is_IPX -- tells if IPX is installed or not					*
    325  *                                                                         *
    326  * INPUT:                                                                  *
    327  *		none.																						*
    328  *                                                                         *
    329  * OUTPUT:                                                                 *
    330  *		1 = IPX is installed; 0 = isn't													*
    331  *                                                                         *
    332  * WARNINGS:                                                               *
    333  *		none.																						*
    334  *                                                                         *
    335  * HISTORY:                                                                *
    336  *   12/20/1994 BR : Created.                                              *
    337  *=========================================================================*/
    338 int IPXManagerClass::Is_IPX(void)
    339 {
    340 	return(IPXStatus);
    341 
    342 }	/* end of Is_IPX */
    343 
    344 
    345 /***************************************************************************
    346  * IPXManagerClass::Set_Timing -- sets timing for all connections				*
    347  *                                                                         *
    348  * This will set the timing parameters for all existing connections, and	*
    349  * all connections created from now on.  This allows an application to		*
    350  * measure the Response_Time while running, and adjust timing accordingly.	*
    351  *                                                                         *
    352  * INPUT:                                                                  *
    353  *		retrydelta	value to set for retry delta 										*
    354  *		maxretries	value to set for max # retries									*
    355  *		timeout		value to set for connection timeout								*
    356  *                                                                         *
    357  * OUTPUT:                                                                 *
    358  *		none.																						*
    359  *                                                                         *
    360  * WARNINGS:                                                               *
    361  *		none.																						*
    362  *                                                                         *
    363  * HISTORY:                                                                *
    364  *   07/02/1995 BR : Created.                                              *
    365  *=========================================================================*/
    366 void IPXManagerClass::Set_Timing (unsigned long retrydelta,
    367 	unsigned long maxretries, unsigned long timeout)
    368 {
    369 	int i;
    370 
    371 	RetryDelta = retrydelta;
    372 	MaxRetries = maxretries;
    373 	Timeout = timeout;
    374 
    375 	if (GlobalChannel) {
    376 		GlobalChannel->Set_Retry_Delta (RetryDelta);
    377 		GlobalChannel->Set_Max_Retries (MaxRetries);
    378 		GlobalChannel->Set_TimeOut (Timeout);
    379 	}
    380 
    381 	for (i = 0; i < NumConnections; i++) {
    382 		Connection[i]->Set_Retry_Delta (RetryDelta);
    383 		Connection[i]->Set_Max_Retries (MaxRetries);
    384 		Connection[i]->Set_TimeOut (Timeout);
    385 	}
    386 
    387 }	/* end of Set_Timing */
    388 
    389 
    390 /***************************************************************************
    391  * IPXManagerClass::Create_Connection -- creates a new connection          *
    392  *                                                                         *
    393  * INPUT:                                                                  *
    394  *		id				application-specific numerical ID for this connection		*
    395  *		node			ptr to IPXNodeIDType (name & address)							*
    396  *		address		IPX address for this connection									*
    397  *                                                                         *
    398  * OUTPUT:                                                                 *
    399  *		1 = OK, 0 = error																		*
    400  *                                                                         *
    401  * WARNINGS:                                                               *
    402  *		Never create a connection with an 'id' of -1.								*
    403  *                                                                         *
    404  * HISTORY:                                                                *
    405  *   12/20/1994 BR : Created.                                              *
    406  *=========================================================================*/
    407 bool IPXManagerClass::Create_Connection(int id, char *name, IPXAddressClass *address)
    408 {
    409 #if (0)
    410 	char temp[80];
    411 
    412 	NetNumType num;
    413 	NetNodeType node;
    414 
    415 	address->Get_Address (num, node);
    416 
    417 	sprintf (temp, "Address:%02x %02x %02x %02x %02x %02x\n", node[0],
    418 														  node[1],
    419 														  node[2],
    420 														  node[3],
    421 														  node[4],
    422 														  node[5]);
    423 	CCDebugString (temp);
    424 
    425 	sprintf (temp, "Network:%02x %02x %02x %02x\n", num[0],
    426 														  num[1],
    427 														  num[2],
    428 														  num[3]);
    429 	CCDebugString (temp);
    430 #endif	//(0)
    431 
    432 	/*
    433 	----------------------- Error if IPX not installed -----------------------
    434 	*/
    435 	if (!IPXStatus)
    436 		return(false);
    437 
    438 	/*
    439 	------------------------- Error if no more room --------------------------
    440 	*/
    441 	if (NumConnections==CONNECT_MAX)
    442 		return(false);
    443 
    444 	/*
    445 	------------------------- Create new connection --------------------------
    446 	*/
    447 	Connection[NumConnections] = new IPXConnClass(Pvt_NumPackets,
    448 		Pvt_NumPackets, Pvt_MaxPacketLen, ProductID, address, id, name);
    449 	if (!Connection[NumConnections])
    450 		return(false);
    451 
    452 	Connection[NumConnections]->Init ();
    453 	Connection[NumConnections]->Set_Retry_Delta (RetryDelta);
    454 	Connection[NumConnections]->Set_Max_Retries (MaxRetries);
    455 	Connection[NumConnections]->Set_TimeOut (Timeout);
    456 
    457 	NumConnections++;
    458 
    459 	return(true);
    460 
    461 }	/* end of Create_Connection */
    462 
    463 
    464 /***************************************************************************
    465  * IPXManagerClass::Delete_Connection -- deletes a connection              *
    466  *                                                                         *
    467  * INPUT:                                                                  *
    468  *		id		ID of connection to delete													*
    469  *                                                                         *
    470  * OUTPUT:                                                                 *
    471  *		1 = OK, 0 = error																		*
    472  *                                                                         *
    473  * WARNINGS:                                                               *
    474  *		none.																						*
    475  *                                                                         *
    476  * HISTORY:                                                                *
    477  *   12/20/1994 BR : Created.                                              *
    478  *=========================================================================*/
    479 bool IPXManagerClass::Delete_Connection(int id)
    480 {
    481 	int i,j;
    482 
    483 	/*
    484 	----------------------- Error if IPX not installed -----------------------
    485 	*/
    486 	if (!IPXStatus)
    487 		return(false);
    488 
    489 	/*
    490 	------------------- Error if no connections to delete --------------------
    491 	*/
    492 	if (NumConnections==0)
    493 		return(false);
    494 
    495 	/*
    496 	---------------------- Loop through all connections ----------------------
    497 	*/
    498 	for (i = 0; i < NumConnections; i++) {
    499 		/*
    500 		........................ If a match, delete it ........................
    501 		*/
    502 		if (Connection[i]->ID==id) {
    503 			delete Connection[i];
    504 			/*
    505 			................ Move array elements back one index ................
    506 			*/
    507 			for (j = i; j < NumConnections - 1; j++) {
    508 				Connection[j] = Connection[j+1];
    509 			}
    510 			/*
    511 			......................... Adjust counters ..........................
    512 			*/
    513 			NumConnections--;
    514 			if (CurConnection >= NumConnections)
    515 				CurConnection = 0;
    516 			return(true);
    517 		}
    518 	}
    519 
    520 	/*
    521 	---------------------------- No match; error -----------------------------
    522 	*/
    523 	return(false);
    524 
    525 }	/* end of Delete_Connection */
    526 
    527 
    528 /***************************************************************************
    529  * IPXManagerClass::Num_Connections -- gets the # of connections				*
    530  *                                                                         *
    531  * INPUT:                                                                  *
    532  *		none.																						*
    533  *                                                                         *
    534  * OUTPUT:                                                                 *
    535  *		# of connections																		*
    536  *                                                                         *
    537  * WARNINGS:                                                               *
    538  *		none.																						*
    539  *                                                                         *
    540  * HISTORY:                                                                *
    541  *   01/25/1995 BR : Created.                                              *
    542  *=========================================================================*/
    543 int IPXManagerClass::Num_Connections(void)
    544 {
    545 #ifdef VIRTUAL_SUBNET_SERVER
    546 	/*
    547 	** If we are connected to the VSS then dont coumt that in the number of connections.
    548 	*/
    549 	if (Connection_Index (VSS_ID) == IPXConnClass::CONNECTION_NONE){
    550 		return(NumConnections);
    551 	}else{
    552 		return(NumConnections -1);
    553 	}
    554 #else	// VIRTUAL_SUBNET_SERVER
    555 
    556 	return(NumConnections);
    557 
    558 #endif	//VIRTUAL_SUBNET_SERVER
    559 
    560 }	/* end of Num_Connections */
    561 
    562 
    563 /***************************************************************************
    564  * IPXManagerClass::Connection_ID -- gets the given connection's ID        *
    565  *                                                                         *
    566  * INPUT:                                                                  *
    567  *		index			index of connection to retrieve									*
    568  *                                                                         *
    569  * OUTPUT:                                                                 *
    570  *		ID for that connection, CONNECTION_NONE if invalid index					*
    571  *                                                                         *
    572  * WARNINGS:                                                               *
    573  *		none.																						*
    574  *                                                                         *
    575  * HISTORY:                                                                *
    576  *   01/25/1995 BR : Created.                                              *
    577  *=========================================================================*/
    578 int IPXManagerClass::Connection_ID(int index)
    579 {
    580 	if (index >= 0 && index < NumConnections) {
    581 		return(Connection[index]->ID);
    582 	} else {
    583 		return(IPXConnClass::CONNECTION_NONE);
    584 	}
    585 }
    586 
    587 
    588 /***************************************************************************
    589  * IPXManagerClass::Connection_Name -- retrieves name for given connection *
    590  *                                                                         *
    591  * INPUT:                                                                  *
    592  *		id		ID of connection to get name of											*
    593  *                                                                         *
    594  * OUTPUT:                                                                 *
    595  *		ptr to connection's name, NULL if not found									*
    596  *                                                                         *
    597  * WARNINGS:                                                               *
    598  *		none.																						*
    599  *                                                                         *
    600  * HISTORY:                                                                *
    601  *   01/19/1995 BR : Created.                                              *
    602  *=========================================================================*/
    603 char *IPXManagerClass::Connection_Name(int id)
    604 {
    605 	int i;
    606 
    607 	for (i = 0; i < NumConnections; i++) {
    608 		if (Connection[i]->ID==id) {
    609 			return(Connection[i]->Name);
    610 		}
    611 	}
    612 
    613 	return(NULL);
    614 
    615 }	/* end of Connection_Name */
    616 
    617 
    618 /***************************************************************************
    619  * IPXManagerClass::Connection_Address -- retrieves connection's address	*
    620  *                                                                         *
    621  * INPUT:                                                                  *
    622  *		id		ID of connection to get address for										*
    623  *                                                                         *
    624  * OUTPUT:                                                                 *
    625  *		pointer to IXPAddressClass, NULL if not found								*
    626  *                                                                         *
    627  * WARNINGS:                                                               *
    628  *		none.																						*
    629  *                                                                         *
    630  * HISTORY:                                                                *
    631  *   01/19/1995 BR : Created.                                              *
    632  *=========================================================================*/
    633 IPXAddressClass * IPXManagerClass::Connection_Address(int id)
    634 {
    635 	int i;
    636 
    637 	for (i = 0; i < NumConnections; i++) {
    638 		if (Connection[i]->ID==id) {
    639 			return(&Connection[i]->Address);
    640 		}
    641 	}
    642 
    643 	return(NULL);
    644 
    645 }	/* end of Connection_Address */
    646 
    647 
    648 /***************************************************************************
    649  * IPXManagerClass::Connection_Index -- gets given connection's index      *
    650  *                                                                         *
    651  * INPUT:                                                                  *
    652  *		ID to retrieve index for															*
    653  *                                                                         *
    654  * OUTPUT:                                                                 *
    655  *		index for this connection, CONNECTION_NONE if not found					*
    656  *                                                                         *
    657  * WARNINGS:                                                               *
    658  *		none.																						*
    659  *                                                                         *
    660  * HISTORY:                                                                *
    661  *   01/25/1995 BR : Created.                                              *
    662  *=========================================================================*/
    663 int IPXManagerClass::Connection_Index(int id)
    664 {
    665 	int i;
    666 
    667 	for (i = 0; i < NumConnections; i++) {
    668 		if (Connection[i]->ID==id)
    669 			return(i);
    670 	}
    671 
    672 	return(IPXConnClass::CONNECTION_NONE);
    673 
    674 }	/* end of Connection_Index */
    675 
    676 
    677 /***************************************************************************
    678  * IPXManagerClass::Send_Global_Message -- sends a Global Message				*
    679  *                                                                         *
    680  * INPUT:                                                                  *
    681  *		buf			buffer to send															*
    682  *		buflen		length of buf															*
    683  *		ack_req		1 = ACK required; 0 = no ACK required							*
    684  *		address		address to send to; NULL = broadcast							*
    685  *                                                                         *
    686  * OUTPUT:                                                                 *
    687  *		1 = OK, 0 = error																		*
    688  *                                                                         *
    689  * WARNINGS:                                                               *
    690  *		none.																						*
    691  *                                                                         *
    692  * HISTORY:                                                                *
    693  *   01/25/1995 BR : Created.                                              *
    694  *=========================================================================*/
    695 int IPXManagerClass::Send_Global_Message(void *buf, int buflen,
    696 	int ack_req, IPXAddressClass *address)
    697 {
    698 	int rc;
    699 
    700 	/*
    701 	------------ Error if IPX not installed or not Listening -----------------
    702 	*/
    703 	if (!IPXStatus || !Listening) return(false);
    704 
    705 	rc = GlobalChannel->Send_Packet (buf, buflen, address, ack_req);
    706 	if (!rc)
    707 		SendOverflows++;
    708 
    709 	return(rc);
    710 }
    711 
    712 
    713 /***************************************************************************
    714  * IPXManagerClass::Get_Global_Message -- polls the Global Message queue	*
    715  *                                                                         *
    716  * INPUT:                                                                  *
    717  *		buf				buffer to store received packet								*
    718  *		buflen			length of data placed in 'buf'								*
    719  *		address			IPX address of sender											*
    720  *		product_id		product ID of sender												*
    721  *                                                                         *
    722  * OUTPUT:                                                                 *
    723  *		1 = OK, 0 = error																		*
    724  *                                                                         *
    725  * WARNINGS:                                                               *
    726  *		none.																						*
    727  *                                                                         *
    728  * HISTORY:                                                                *
    729  *   01/25/1995 BR : Created.                                              *
    730  *=========================================================================*/
    731 int IPXManagerClass::Get_Global_Message(void *buf, int *buflen,
    732 	IPXAddressClass *address, unsigned short *product_id)
    733 {
    734 	/*
    735 	------------ Error if IPX not installed or not Listening -----------------
    736 	*/
    737 	if (!IPXStatus || !Listening) return(false);
    738 
    739 	return(GlobalChannel->Get_Packet (buf, buflen, address, product_id));
    740 }
    741 
    742 
    743 /***************************************************************************
    744  * IPXManagerClass::Send_Private_Message -- Sends a Private Message			*
    745  *                                                                         *
    746  * INPUT:                                                                  *
    747  *		buf			buffer to send															*
    748  *		buflen		length of 'buf'														*
    749  *		conn_id		connection ID to send to (CONNECTION_NONE = all)			*
    750  *		ack_req		1 = ACK required; 0 = no ACK required							*
    751  *                                                                         *
    752  * OUTPUT:                                                                 *
    753  *		1 = OK, 0 = error																		*
    754  *                                                                         *
    755  * WARNINGS:                                                               *
    756  *		none.																						*
    757  *                                                                         *
    758  * HISTORY:                                                                *
    759  *   01/25/1995 BR : Created.                                              *
    760  *=========================================================================*/
    761 int IPXManagerClass::Send_Private_Message(void *buf, int buflen, int ack_req,
    762 	int conn_id)
    763 {
    764 	int i;						// loop counter
    765 	int connect_idx;			// index of channel to send to, if specified
    766 
    767 	/*
    768 	------------ Error if IPX not installed or not Listening -----------------
    769 	*/
    770 	if (!IPXStatus || !Listening || (NumConnections==0)) return(false);
    771 
    772 	/*------------------------------------------------------------------------
    773 	Send the message to all connections
    774 	------------------------------------------------------------------------*/
    775 	if (conn_id==IPXConnClass::CONNECTION_NONE) {
    776 
    777 		/*
    778 		** If this is an internet game and no ack is reqired then we only need to send
    779 		**	 the packet to the VSS and it will forward it to all the other players.
    780 		*/
    781 
    782 #ifdef VIRTUAL_SUBNET_SERVER
    783 		if (ack_req || (!Winsock.Get_Connected() || !UseVirtualSubnetServer)){
    784 #endif	//VIRTUAL_SUBNET_SERVER
    785 			/*.....................................................................
    786 			Check for room in all connections
    787 			.....................................................................*/
    788 			for (i = 0; i < NumConnections; i++) {
    789 #ifdef VIRTUAL_SUBNET_SERVER
    790 				if (Connection[i]->ID != VSS_ID){
    791 #endif	//VIRTUAL_SUBNET_SERVER
    792 					if (Connection[i]->Queue->Num_Send()==Connection[i]->Queue->Max_Send()) {
    793 						SendOverflows++;
    794 						return(false);
    795 					}
    796 #ifdef VIRTUAL_SUBNET_SERVER
    797 				}
    798 #endif	// VIRTUAL_SUBNET_SERVER
    799 			}
    800 
    801 			/*.....................................................................
    802 			Send packet to all connections
    803 			.....................................................................*/
    804 
    805 			for (i = 0; i < NumConnections; i++) {
    806 #ifdef VIRTUAL_SUBNET_SERVER
    807 				if (Connection[i]->ID != VSS_ID){
    808 #endif	//VIRTUAL_SUBNET_SERVER
    809 					Connection[i]->Send_Packet (buf, buflen, ack_req);
    810 #ifdef VIRTUAL_SUBNET_SERVER
    811 				}
    812 #endif	//VIRTUAL_SUBNET_SERVER
    813 			}
    814 
    815 #ifdef VIRTUAL_SUBNET_SERVER
    816 		}else{
    817 			/*
    818 			** Send the packet to the VSS with a 0 header so it gets forwarded to all players.
    819 			*/
    820 			if (Connection[ Connection_Index(VSS_ID) ]->Queue->Num_Send() == Connection[ Connection_Index(VSS_ID) ]->Queue->Max_Send()) {
    821 				SendOverflows++;
    822 				return(false);
    823 			}
    824 			Connection[ Connection_Index(VSS_ID) ]->Send_Packet (buf, buflen, 0);
    825 		}
    826 #endif	// VIRTUAL_SUBNET_SERVER
    827 
    828 		return(true);
    829 
    830 
    831 	} else {
    832 
    833 		/*------------------------------------------------------------------------
    834 		Send the message to the specified connection
    835 		------------------------------------------------------------------------*/
    836 		connect_idx = Connection_Index (conn_id);
    837 		if (connect_idx == IPXConnClass::CONNECTION_NONE) {
    838 			SendOverflows++;
    839 			return(false);
    840 		}
    841 
    842 		/*.....................................................................
    843 		Check for room in the connection
    844 		.....................................................................*/
    845 		if (Connection[connect_idx]->Queue->Num_Send() ==
    846 			Connection[connect_idx]->Queue->Max_Send()) {
    847 			SendOverflows++;
    848 			return(false);
    849 		}
    850 
    851 		/*.....................................................................
    852 		Send the packet to that connection
    853 		.....................................................................*/
    854 		Connection[connect_idx]->Send_Packet (buf, buflen, ack_req);
    855 		return(true);
    856 	}
    857 }
    858 
    859 
    860 /***************************************************************************
    861  * IPXManagerClass::Get_Private_Message -- Polls the Private Message queue	*
    862  *                                                                         *
    863  * INPUT:                                                                  *
    864  *		buf			buffer to store incoming packet									*
    865  *		buflen		length of data placed in 'buf'									*
    866  *		conn_id		filled in with connection ID of sender							*
    867  *                                                                         *
    868  * OUTPUT:                                                                 *
    869  *		1 = OK, 0 = error																		*
    870  *                                                                         *
    871  * WARNINGS:                                                               *
    872  *		none.																						*
    873  *                                                                         *
    874  * HISTORY:                                                                *
    875  *   01/25/1995 BR : Created.                                              *
    876  *=========================================================================*/
    877 int IPXManagerClass::Get_Private_Message(void *buf, int *buflen, int *conn_id)
    878 {
    879 	int i;
    880 	int rc;
    881 	int c_id;
    882 #ifdef VIRTUAL_SUBNET_SERVER
    883 	int vss = 0;
    884 #endif	// VIRTUAL_SUBNET_SERVER
    885 
    886 	/*
    887 	------------ Error if IPX not installed or not Listening -----------------
    888 	*/
    889 	if (!IPXStatus || !Listening || (NumConnections==0)) return(false);
    890 
    891 #ifdef VIRTUAL_SUBNET_SERVER
    892 	if (Winsock.Get_Connected()){
    893 		vss = (int) UseVirtualSubnetServer;
    894 	}
    895 #endif	//VIRTUAL_SUBNET_SERVER
    896 
    897 	/*------------------------------------------------------------------------
    898 	Safety check: ensure CurConnection is in range.
    899 	------------------------------------------------------------------------*/
    900 #ifdef VIRTUAL_SUBNET_SERVER
    901 	if (CurConnection >= NumConnections - vss)
    902 #else	// VIRTUAL_SUBNET_SERVER
    903 	if (CurConnection >= NumConnections)
    904 #endif	//VIRTUAL_SUBNET_SERVER
    905 		CurConnection = 0;
    906 
    907 	/*------------------------------------------------------------------------
    908 	Scan all connections for a received packet, starting with 'CurConnection'
    909 	------------------------------------------------------------------------*/
    910 #ifdef VIRTUAL_SUBNET_SERVER
    911 	for (i = 0; i < NumConnections - vss; i++) {
    912 #else	// VIRTUAL_SUBNET_SERVER
    913 	for (i = 0; i < NumConnections; i++) {
    914 #endif	// VIRTUAL_SUBNET_SERVER
    915 		/*.....................................................................
    916 		Check this connection for a packet
    917 		.....................................................................*/
    918 		rc = Connection[CurConnection]->Get_Packet (buf, buflen);
    919 		c_id = Connection[CurConnection]->ID;
    920 
    921 		/*.....................................................................
    922 		Increment CurConnection to the next connection index
    923 		.....................................................................*/
    924 		CurConnection++;
    925 #ifdef VIRTUAL_SUBNET_SERVER
    926 		if (CurConnection >= NumConnections - vss)
    927 #else	// VIRTUAL_SUBNET_SERVER
    928 		if (CurConnection >= NumConnections)
    929 #endif	// VIRTUAL_SUBNET_SERVER
    930 			CurConnection = 0;
    931 
    932 		/*.....................................................................
    933 		If we got a packet, return the connection ID
    934 		.....................................................................*/
    935 		if (rc) {
    936 			(*conn_id) = c_id;
    937 			return(true);
    938 		}
    939 	}
    940 
    941 	return(false);
    942 }
    943 
    944 
    945 /***************************************************************************
    946  * IPXManagerClass::Service -- main polling routine for IPX Connections		*
    947  *                                                                         *
    948  * INPUT:                                                                  *
    949  *		none.																						*
    950  *                                                                         *
    951  * OUTPUT:                                                                 *
    952  *		1 = OK, 0 = error																		*
    953  *                                                                         *
    954  * WARNINGS:                                                               *
    955  *		none.																						*
    956  *                                                                         *
    957  * HISTORY:                                                                *
    958  *   01/25/1995 BR : Created.                                              *
    959  *=========================================================================*/
    960 int IPXManagerClass::Service(void)
    961 {
    962 
    963 	int rc = 1;
    964 	int i;
    965 	CommHeaderType *packet;
    966 	int packetlen;
    967 	IPXAddressClass address;
    968 
    969 
    970 
    971 #ifndef NOT_FOR_WIN95
    972 
    973 	unsigned char temp_receive_buffer[1024];
    974 	int	recv_length;
    975 
    976 	if (Winsock.Get_Connected()){
    977 
    978 		while ((recv_length = Winsock.Read(temp_receive_buffer, 1024))!=0){
    979 
    980 #ifdef VIRTUAL_SUBNET_SERVER
    981 			/*
    982 			** Get a pointer to the data header and swap the bit mask
    983 			*/
    984 			CurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0]; 	//NULL;
    985 			unsigned short *swapptr = (unsigned short*)CurHeaderBuf;
    986 			*swapptr = ntohs (*swapptr);
    987 
    988 			CurDataBuf = (char*)&temp_receive_buffer[2];
    989 
    990 			/*.....................................................................
    991 			Compute the length of the packet (byte-swap the length in the IPX hdr)
    992 			.....................................................................*/
    993 			packetlen = recv_length-2;
    994 #else	//VIRTUAL_SUBNET_SERVER
    995 			CurHeaderBuf = NULL;
    996 			CurDataBuf = (char*)&temp_receive_buffer[0];
    997 
    998 			/*.....................................................................
    999 			Compute the length of the packet (byte-swap the length in the IPX hdr)
   1000 			.....................................................................*/
   1001 			packetlen = recv_length;
   1002 
   1003 #endif	//VIRTUAL_SUBNET_SERVER
   1004 
   1005 
   1006 			/*.....................................................................
   1007 			Extract the sender's address from the IPX header
   1008 			.....................................................................*/
   1009 			address.Set_Address (CurHeaderBuf);
   1010 
   1011 			/*.....................................................................
   1012 			Examine the Magic Number of the received packet to determine if this
   1013 			packet goes into the Global Queue, or into one of the Private Queues
   1014 			.....................................................................*/
   1015 			packet = (CommHeaderType *)CurDataBuf;
   1016 #if (0)
   1017 char tempbuf[256];
   1018 
   1019 static char pcode [4][18]={
   1020 	"PACKET_DATA_ACK",			// this is a data packet requiring an ACK
   1021  	"PACKET_DATA_NOACK",		// this is a data packet not requiring an ACK
   1022 	"PACKET_ACK",					// this is an ACK for a packet
   1023 	"PACKET_COUNT"				// for computational purposes
   1024 };
   1025 
   1026 sprintf (tempbuf, "Received packet type %d, ID=%d, code=%s, length=%d \n", CurDataBuf[sizeof(CommHeaderType)],
   1027 																						packet->PacketID,
   1028 																						pcode[packet->Code],
   1029 																						recv_length);
   1030 CCDebugString (tempbuf);
   1031 #endif	//(0)
   1032 			if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1033 				/*..................................................................
   1034 				Put the packet in the Global Queue
   1035 				..................................................................*/
   1036 				if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1037 					ReceiveOverflows++;
   1038 			} else {
   1039 				if (packet->MagicNumber == ProductID) {
   1040 					/*..................................................................
   1041 					Find the Private Queue that this packet is for
   1042 					..................................................................*/
   1043 					for (i = 0; i < NumConnections; i++) {
   1044 #ifdef VIRTUAL_SUBNET_SERVER
   1045 						if (Connection[i]->Address == address && Connection[i]->ID != VSS_ID) {
   1046 #else	//VIRTUAL_SUBNET_SERVER
   1047 						if (Connection[i]->Address == address) {
   1048 #endif	//VIRTUAL_SUBNET_SERVER
   1049 							if (!Connection[i]->Receive_Packet (packet, packetlen))
   1050 								ReceiveOverflows++;
   1051 							break;
   1052 						}
   1053 					}
   1054 				}
   1055 			}
   1056 
   1057 		}
   1058 	}else{
   1059 
   1060 		while (IPX_Get_Outstanding_Buffer95(&temp_receive_buffer[0])){
   1061 
   1062 			CurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0];
   1063 			CurDataBuf = (char*)&temp_receive_buffer[sizeof(IPXHeaderType)];
   1064 
   1065 			/*.....................................................................
   1066 			Compute the length of the packet (byte-swap the length in the IPX hdr)
   1067 			.....................................................................*/
   1068 			packetlen = ((CurHeaderBuf->Length & 0xff) << 8) |
   1069 				(CurHeaderBuf->Length >> 8);
   1070 			packetlen -= sizeof(IPXHeaderType);
   1071 
   1072 			/*.....................................................................
   1073 			Extract the sender's address from the IPX header
   1074 			.....................................................................*/
   1075 			address.Set_Address (CurHeaderBuf);
   1076 
   1077 			/*.....................................................................
   1078 			Examine the Magic Number of the received packet to determine if this
   1079 			packet goes into the Global Queue, or into one of the Private Queues
   1080 			.....................................................................*/
   1081 			packet = (CommHeaderType *)CurDataBuf;
   1082 
   1083 			if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1084 				/*..................................................................
   1085 				Put the packet in the Global Queue
   1086 				..................................................................*/
   1087 				if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1088 					ReceiveOverflows++;
   1089 			} else {
   1090 				if (packet->MagicNumber == ProductID) {
   1091 					/*..................................................................
   1092 					Find the Private Queue that this packet is for
   1093 					..................................................................*/
   1094 					for (i = 0; i < NumConnections; i++) {
   1095 						if (Connection[i]->Address == address) {
   1096 							if (!Connection[i]->Receive_Packet (packet, packetlen))
   1097 								ReceiveOverflows++;
   1098 							break;
   1099 						}
   1100 					}
   1101 				}
   1102 			}
   1103 
   1104 		}
   1105 	}
   1106 
   1107 	//IPX_Start_Listening95();
   1108 
   1109 
   1110 #else //NOT_FOR_WIN95
   1111 
   1112 
   1113 	/*
   1114 	------------ Error if IPX not installed or not Listening -----------------
   1115 	*/
   1116 	if (!IPXStatus || !Listening)
   1117 		return(false);
   1118 
   1119 	/*------------------------------------------------------------------------
   1120 	Loop until there are no more packets to process.
   1121 	------------------------------------------------------------------------*/
   1122 	for (;;) {
   1123 		/*.....................................................................
   1124 		Check the BufferFlags for the "current" buffer; if it's empty,
   1125 		break; out of the loop.
   1126 		.....................................................................*/
   1127 		if (BufferFlags[CurIndex]==0)
   1128 			break;
   1129 
   1130 		/*.....................................................................
   1131 		Compute the length of the packet (byte-swap the length in the IPX hdr)
   1132 		.....................................................................*/
   1133 		packetlen = ((CurHeaderBuf->Length & 0xff) << 8) |
   1134 			(CurHeaderBuf->Length >> 8);
   1135 		packetlen -= sizeof(IPXHeaderType);
   1136 
   1137 		/*.....................................................................
   1138 		Extract the sender's address from the IPX header
   1139 		.....................................................................*/
   1140 		address.Set_Address (CurHeaderBuf);
   1141 
   1142 		/*.....................................................................
   1143 		Examine the Magic Number of the received packet to determine if this
   1144 		packet goes into the Global Queue, or into one of the Private Queues
   1145 		.....................................................................*/
   1146 		packet = (CommHeaderType *)CurDataBuf;
   1147 		if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1148 			/*..................................................................
   1149 			Put the packet in the Global Queue
   1150 			..................................................................*/
   1151 			if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1152 				ReceiveOverflows++;
   1153 		} else {
   1154 			if (packet->MagicNumber == ProductID) {
   1155 				/*..................................................................
   1156 				Find the Private Queue that this packet is for
   1157 				..................................................................*/
   1158 				for (i = 0; i < NumConnections; i++) {
   1159 					if (Connection[i]->Address == address) {
   1160 						if (!Connection[i]->Receive_Packet (packet, packetlen))
   1161 							ReceiveOverflows++;
   1162 						break;
   1163 					}
   1164 				}
   1165 			}
   1166 		}
   1167 
   1168 		/*.....................................................................
   1169 		Set the current BufferFlags to 0 (since we've cleaned out this buffer)
   1170 		.....................................................................*/
   1171 		BufferFlags[CurIndex] = 0;
   1172 
   1173 		/*.....................................................................
   1174 		Go to the next packet buffer
   1175 		.....................................................................*/
   1176 		CurIndex++;
   1177 		CurHeaderBuf = (IPXHeaderType *)(((char *)CurHeaderBuf) + FullPacketLen);
   1178 		CurDataBuf = ((char *)CurDataBuf) + FullPacketLen;
   1179 		if (CurIndex >= NumBufs) {
   1180 			CurHeaderBuf = FirstHeaderBuf;
   1181 			CurDataBuf = FirstDataBuf;
   1182 			CurIndex = 0;
   1183 		}
   1184 
   1185 	}
   1186 
   1187 #endif //NOT_FOR_WIN95
   1188 
   1189 	/*------------------------------------------------------------------------
   1190 	Service all connections.  If a connection reports that it's gone "bad",
   1191 	report an error to the caller.  If it's the Global Channel, un-queue the
   1192 	send entry that's holding things up.  This will keep the Global Channel
   1193 	from being clogged by one un-ACK'd outgoing packet.
   1194 	------------------------------------------------------------------------*/
   1195 	if (GlobalChannel) {
   1196 		if (!GlobalChannel->Service()) {
   1197 			GlobalChannel->Queue->UnQueue_Send (NULL, NULL, 0);
   1198 			rc = 0;
   1199 		}
   1200 	}
   1201 	for (i = 0; i < NumConnections; i++) {
   1202 		if (!Connection[i]->Service()) {
   1203 #ifdef VIRTUAL_SUBNET_SERVER
   1204 			if (Connection[i]->ID != VSS_ID){
   1205 #endif	//VIRTUAL_SUBNET_SERVER
   1206 				rc = 0;
   1207 				BadConnection = Connection[i]->ID;
   1208 #ifdef VIRTUAL_SUBNET_SERVER
   1209 			}
   1210 #endif	//VIRTUAL_SUBNET_SERVER
   1211 		}
   1212 	}
   1213 
   1214 	if (rc)
   1215 		BadConnection = IPXConnClass::CONNECTION_NONE;
   1216 
   1217 	return(rc);
   1218 
   1219 
   1220 }	/* end of Service */
   1221 
   1222 
   1223 /***************************************************************************
   1224  * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID        *
   1225  *                                                                         *
   1226  * INPUT:                                                                  *
   1227  *		none.																						*
   1228  *                                                                         *
   1229  * OUTPUT:                                                                 *
   1230  *		ID of bad connection; CONNECTION_NONE if none.								*
   1231  *                                                                         *
   1232  * WARNINGS:                                                               *
   1233  *		none.																						*
   1234  *                                                                         *
   1235  * HISTORY:                                                                *
   1236  *   05/04/1995 BRR : Created.                                             *
   1237  *=========================================================================*/
   1238 int IPXManagerClass::Get_Bad_Connection(void)
   1239 {
   1240 	return(BadConnection);
   1241 
   1242 }	/* end of Get_Bad_Connection */
   1243 
   1244 
   1245 /***************************************************************************
   1246  * IPXManagerClass::Global_Num_Send	-- reports # entries in send queue		*
   1247  *                                                                         *
   1248  * INPUT:                                                                  *
   1249  *		none.																						*
   1250  *                                                                         *
   1251  * OUTPUT:                                                                 *
   1252  *		# entries in the Global Send Queue												*
   1253  *                                                                         *
   1254  * WARNINGS:                                                               *
   1255  *		none.																						*
   1256  *                                                                         *
   1257  * HISTORY:                                                                *
   1258  *   01/25/1995 BR : Created.                                              *
   1259  *=========================================================================*/
   1260 int IPXManagerClass::Global_Num_Send(void)
   1261 {
   1262 	/*
   1263 	------------ Error if IPX not installed or not Listening -----------------
   1264 	*/
   1265 	if (!IPXStatus || !Listening)
   1266 		return(0);
   1267 
   1268 	return(GlobalChannel->Queue->Num_Send());
   1269 
   1270 }	/* end of Global_Num_Send */
   1271 
   1272 
   1273 /***************************************************************************
   1274  * IPXManagerClass::Global_Num_Receive -- reports # entries in recv queue	*
   1275  *                                                                         *
   1276  * INPUT:                                                                  *
   1277  *		none.																						*
   1278  *                                                                         *
   1279  * OUTPUT:                                                                 *
   1280  *		# entries in the Global Receive Queue											*
   1281  *                                                                         *
   1282  * WARNINGS:                                                               *
   1283  *		none.																						*
   1284  *                                                                         *
   1285  * HISTORY:                                                                *
   1286  *   01/25/1995 BR : Created.                                              *
   1287  *=========================================================================*/
   1288 int IPXManagerClass::Global_Num_Receive(void)
   1289 {
   1290 	/*
   1291 	------------ Error if IPX not installed or not Listening -----------------
   1292 	*/
   1293 	if (!IPXStatus || !Listening)
   1294 		return(0);
   1295 
   1296 	return(GlobalChannel->Queue->Num_Receive());
   1297 
   1298 }	/* end of Global_Num_Receive */
   1299 
   1300 
   1301 /***************************************************************************
   1302  * IPXManagerClass::Private_Num_Send -- reports # entries in send queue		*
   1303  *                                                                         *
   1304  * INPUT:                                                                  *
   1305  *		# entries in the Private Send Queue												*
   1306  *                                                                         *
   1307  * OUTPUT:                                                                 *
   1308  *		1 = OK, 0 = error																		*
   1309  *                                                                         *
   1310  * WARNINGS:                                                               *
   1311  *		none.																						*
   1312  *                                                                         *
   1313  * HISTORY:                                                                *
   1314  *   01/25/1995 BR : Created.                                              *
   1315  *=========================================================================*/
   1316 int IPXManagerClass::Private_Num_Send(int id)
   1317 {
   1318 	int i;
   1319 	int maxnum;
   1320 
   1321 	/*
   1322 	------------ Error if IPX not installed or not Listening -----------------
   1323 	*/
   1324 	if (!IPXStatus || !Listening || (NumConnections==0)) return(false);
   1325 
   1326 	/*------------------------------------------------------------------------
   1327 	If connection ID specified, return that connection's # of packets
   1328 	------------------------------------------------------------------------*/
   1329 	if (id != IPXConnClass::CONNECTION_NONE) {
   1330 		i = Connection_Index(id);
   1331 		if (i != IPXConnClass::CONNECTION_NONE) {
   1332 			return(Connection[i]->Queue->Num_Send());
   1333 		} else {
   1334 			return(false);
   1335 		}
   1336 	} else {
   1337 
   1338 		/*------------------------------------------------------------------------
   1339 		Otherwise, return the max # of all connections
   1340 		------------------------------------------------------------------------*/
   1341 		maxnum = 0;
   1342 		for (i = 0; i < NumConnections; i++) {
   1343 			if (Connection[i]->Queue->Num_Send() > maxnum) {
   1344 				maxnum = Connection[i]->Queue->Num_Send();
   1345 			}
   1346 		}
   1347 		return(maxnum);
   1348 	}
   1349 }
   1350 
   1351 
   1352 /***************************************************************************
   1353  * IPXManagerClass::Private_Num_Receive -- reports # entries in recv queue	*
   1354  *                                                                         *
   1355  * INPUT:                                                                  *
   1356  *		id		ID of connection to query													*
   1357  *                                                                         *
   1358  * OUTPUT:                                                                 *
   1359  *		# entries in the Private Receive Queue											*
   1360  *                                                                         *
   1361  * WARNINGS:                                                               *
   1362  *		none.																						*
   1363  *                                                                         *
   1364  * HISTORY:                                                                *
   1365  *   01/25/1995 BR : Created.                                              *
   1366  *=========================================================================*/
   1367 int IPXManagerClass::Private_Num_Receive(int id)
   1368 {
   1369 	int i;
   1370 	int maxnum;
   1371 
   1372 	/*
   1373 	------------ Error if IPX not installed or not Listening -----------------
   1374 	*/
   1375 	if (!IPXStatus || !Listening || (NumConnections==0))
   1376 		return(0);
   1377 
   1378 	/*------------------------------------------------------------------------
   1379 	If connection ID specified, return that connection's # of packets
   1380 	------------------------------------------------------------------------*/
   1381 	if (id != IPXConnClass::CONNECTION_NONE) {
   1382 		i = Connection_Index(id);
   1383 		if (i != IPXConnClass::CONNECTION_NONE) {
   1384 			return(Connection[i]->Queue->Num_Receive());
   1385 		} else {
   1386 			return(0);
   1387 		}
   1388 	} else {
   1389 
   1390 		/*------------------------------------------------------------------------
   1391 		Otherwise, return the max # of all connections
   1392 		------------------------------------------------------------------------*/
   1393 		maxnum = 0;
   1394 		for (i = 0; i < NumConnections; i++) {
   1395 			if (Connection[i]->Queue->Num_Receive() > maxnum)
   1396 				maxnum = Connection[i]->Queue->Num_Receive();
   1397 		}
   1398 		return(maxnum);
   1399 	}
   1400 }
   1401 
   1402 
   1403 /***************************************************************************
   1404  * IPXManagerClass::Set_Socket -- sets socket ID for all connections			*
   1405  *                                                                         *
   1406  * INPUT:                                                                  *
   1407  *		socket	new socket ID to use														*
   1408  *                                                                         *
   1409  * OUTPUT:                                                                 *
   1410  *		none.																						*
   1411  *                                                                         *
   1412  * WARNINGS:                                                               *
   1413  *		Do not call this function after communications have started; you		*
   1414  *		must call it before calling Init().												*
   1415  *		The socket number is byte-swapped, since IPX requires socket ID's		*
   1416  *		to be stored high/low.																*
   1417  *                                                                         *
   1418  * HISTORY:                                                                *
   1419  *   01/25/1995 BR : Created.                                              *
   1420  *=========================================================================*/
   1421 void IPXManagerClass::Set_Socket(unsigned short socket)
   1422 {
   1423 	Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |
   1424 		(((unsigned long)socket & 0xff00) >> 8));
   1425 
   1426 }	/* end of Set_Socket */
   1427 
   1428 
   1429 /***************************************************************************
   1430  * IPXManagerClass::Response_Time -- Returns largest Avg Response Time     *
   1431  *                                                                         *
   1432  * INPUT:                                                                  *
   1433  *		none.																						*
   1434  *                                                                         *
   1435  * OUTPUT:                                                                 *
   1436  *		largest avg response time															*
   1437  *                                                                         *
   1438  * WARNINGS:                                                               *
   1439  *		none.																						*
   1440  *                                                                         *
   1441  * HISTORY:                                                                *
   1442  *   05/04/1995 BRR : Created.                                             *
   1443  *=========================================================================*/
   1444 unsigned long IPXManagerClass::Response_Time(void)
   1445 {
   1446 	unsigned long resp;
   1447 	unsigned long maxresp = 0;
   1448 	int i;
   1449 #ifdef VIRTUAL_SUBNET_SERVER
   1450 	int vss=0;
   1451 
   1452 	if (Winsock.Get_Connected()){
   1453 		vss = (int) UseVirtualSubnetServer;
   1454 	}
   1455 
   1456 	for (i = 0; i < NumConnections - vss; i++) {
   1457 #else //VIRTUAL_SUBNET_SERVER
   1458 	for (i = 0; i < NumConnections; i++) {
   1459 #endif	// VIRTUAL_SUBNET_SERVER
   1460 		resp = Connection[i]->Queue->Avg_Response_Time();
   1461 		if (resp > maxresp)
   1462 			maxresp = resp;
   1463 	}
   1464 
   1465 	return(maxresp);
   1466 }
   1467 
   1468 
   1469 /***************************************************************************
   1470  * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time      *
   1471  *                                                                         *
   1472  * INPUT:                                                                  *
   1473  *		none.																						*
   1474  *                                                                         *
   1475  * OUTPUT:                                                                 *
   1476  *		avg global channel response time													*
   1477  *                                                                         *
   1478  * WARNINGS:                                                               *
   1479  *		none.																						*
   1480  *                                                                         *
   1481  * HISTORY:                                                                *
   1482  *   05/04/1995 BRR : Created.                                             *
   1483  *=========================================================================*/
   1484 unsigned long IPXManagerClass::Global_Response_Time(void)
   1485 {
   1486 	if (GlobalChannel) {
   1487 		return (GlobalChannel->Queue->Avg_Response_Time());
   1488 	} else {
   1489 		return (0);
   1490 	}
   1491 }
   1492 
   1493 
   1494 /***************************************************************************
   1495  * IPXManagerClass::Reset_Response_Time -- Reset response time					*
   1496  *                                                                         *
   1497  * INPUT:                                                                  *
   1498  *		none.																						*
   1499  *                                                                         *
   1500  * OUTPUT:                                                                 *
   1501  *		none.																						*
   1502  *                                                                         *
   1503  * WARNINGS:                                                               *
   1504  *		none.																						*
   1505  *                                                                         *
   1506  * HISTORY:                                                                *
   1507  *   05/04/1995 BRR : Created.                                             *
   1508  *=========================================================================*/
   1509 void IPXManagerClass::Reset_Response_Time(void)
   1510 {
   1511 	int i;
   1512 
   1513 	for (i = 0; i < NumConnections; i++) {
   1514 		Connection[i]->Queue->Reset_Response_Time();
   1515 	}
   1516 
   1517 	if (GlobalChannel)
   1518 		GlobalChannel->Queue->Reset_Response_Time();
   1519 
   1520 }	/* end of Reset_Response_Time */
   1521 
   1522 
   1523 /***************************************************************************
   1524  * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf             *
   1525  *                                                                         *
   1526  * INPUT:                                                                  *
   1527  *		none.																						*
   1528  *                                                                         *
   1529  * OUTPUT:                                                                 *
   1530  *		buf ptr																					*
   1531  *                                                                         *
   1532  * WARNINGS:                                                               *
   1533  *		none.																						*
   1534  *                                                                         *
   1535  * HISTORY:                                                                *
   1536  *   05/04/1995 BRR : Created.                                             *
   1537  *=========================================================================*/
   1538 void * IPXManagerClass::Oldest_Send(void)
   1539 {
   1540 	int i,j;
   1541 	unsigned long time;
   1542 	unsigned long mintime = 0xffffffff;
   1543 	SendQueueType *send_entry;				// ptr to send entry header
   1544 	CommHeaderType *packet;
   1545 	void *buf = NULL;
   1546 
   1547 	for (i = 0; i < NumConnections; i++) {
   1548 
   1549 		send_entry = NULL;
   1550 
   1551 		for (j = 0; j < Connection[i]->Queue->Num_Send(); j++) {
   1552 			send_entry = Connection[i]->Queue->Get_Send(j);
   1553 			if (send_entry) {
   1554 				packet = (CommHeaderType *)send_entry->Buffer;
   1555 				if (packet->Code == ConnectionClass::PACKET_DATA_ACK && send_entry->IsACK == 0) {
   1556 					break;
   1557 				} else {
   1558 					send_entry = NULL;
   1559 				}
   1560 			}
   1561 		}
   1562 
   1563 		if (send_entry!=NULL) {
   1564 
   1565 			time = send_entry->FirstTime;
   1566 
   1567 			if (time < mintime) {
   1568 				mintime = time;
   1569 				buf = send_entry->Buffer;
   1570 			}
   1571 		}
   1572 	}
   1573 
   1574 	return(buf);
   1575 
   1576 }	/* end of Oldest_Send */
   1577 
   1578 
   1579 /***************************************************************************
   1580  * IPXManagerClass::Set_Bridge -- prepares to cross a bridge               *
   1581  *                                                                         *
   1582  * This routine is designed to prevent the connection from having to			*
   1583  * call Get_Local_Target, except the minimum number of times, since that	*
   1584  * routine is buggy & goes away for long periods sometimes.						*
   1585  *                                                                         *
   1586  * INPUT:                                                                  *
   1587  *		bridge		network number of the destination bridge						*
   1588  *                                                                         *
   1589  * OUTPUT:                                                                 *
   1590  *		none																						*
   1591  *                                                                         *
   1592  * WARNINGS:                                                               *
   1593  *		none																						*
   1594  *                                                                         *
   1595  * HISTORY:                                                                *
   1596  *   07/06/1995 BRR : Created.                                             *
   1597  *=========================================================================*/
   1598 void IPXManagerClass::Set_Bridge(NetNumType bridge)
   1599 {
   1600 	if (GlobalChannel) {
   1601 		GlobalChannel->Set_Bridge(bridge);
   1602 	}
   1603 }
   1604 
   1605 
   1606 /***************************************************************************
   1607  * IPXManagerClass::Configure_Debug -- sets up special debug values        *
   1608  *                                                                         *
   1609  * Mono_Debug_Print2() can look into a packet to pull out a particular		*
   1610  * ID, and can print both that ID and a string corresponding to				*
   1611  * that ID.  This routine configures these values so it can find				*
   1612  * and decode the ID.  This ID is used in addition to the normal				*
   1613  * CommHeaderType values.																	*
   1614  *                                                                         *
   1615  * INPUT:                                                                  *
   1616  *		index			connection index to configure (-1 = Global Channel)		*
   1617  *		offset		ID's byte offset into packet										*
   1618  *		size			size of ID, in bytes; 0 if none									*
   1619  *		names			ptr to array of names; use ID as an index into this		*
   1620  *		maxnames		max # in the names array; 0 if none.							*
   1621  *                                                                         *
   1622  * OUTPUT:                                                                 *
   1623  *		none.																						*
   1624  *                                                                         *
   1625  * WARNINGS:                                                               *
   1626  *		Names shouldn't be longer than 12 characters.								*
   1627  *                                                                         *
   1628  * HISTORY:                                                                *
   1629  *   05/31/1995 BRR : Created.                                             *
   1630  *=========================================================================*/
   1631 void IPXManagerClass::Configure_Debug(int index, int offset, int size,
   1632 	char **names, int maxnames)
   1633 {
   1634 	if (index == -1) {
   1635 		GlobalChannel->Queue->Configure_Debug (offset, size, names, maxnames);
   1636 	} else {
   1637 		if (Connection[index]) {
   1638 			Connection[index]->Queue->Configure_Debug (offset, size, names, maxnames);
   1639 		}
   1640 	}
   1641 }
   1642 
   1643 
   1644 /***************************************************************************
   1645  * IPXManagerClass::Mono_Debug_Print -- debug output routine					*
   1646  *                                                                         *
   1647  * INPUT:                                                                  *
   1648  *		index			index of connection to display (-1 = Global Channel)		*
   1649  *		refresh		1 = complete screen refresh										*
   1650  *                                                                         *
   1651  * OUTPUT:                                                                 *
   1652  *		1 = OK, 0 = error																		*
   1653  *                                                                         *
   1654  * WARNINGS:                                                               *
   1655  *		none.																						*
   1656  *                                                                         *
   1657  * HISTORY:                                                                *
   1658  *   01/25/1995 BR : Created.                                              *
   1659  *=========================================================================*/
   1660 void IPXManagerClass::Mono_Debug_Print(int index, int refresh)
   1661 {
   1662 #ifdef WWLIB32_H
   1663 	char txt[80];
   1664 	int i;
   1665 
   1666 	if (index == -1)
   1667 		GlobalChannel->Queue->Mono_Debug_Print (refresh);
   1668 	else if (Connection[index])
   1669 		Connection[index]->Queue->Mono_Debug_Print (refresh);
   1670 
   1671 	if (refresh) {
   1672 		Mono_Set_Cursor (20,1);
   1673 		Mono_Printf ("IPX Queue:");
   1674 
   1675 		Mono_Set_Cursor (9,2);
   1676 		Mono_Printf ("Average Response Time:");
   1677 
   1678 		Mono_Set_Cursor (43,1);
   1679 		Mono_Printf ("Send Overflows:");
   1680 
   1681 		Mono_Set_Cursor (40,2);
   1682 		Mono_Printf ("Receive Overflows:");
   1683 
   1684 	}
   1685 
   1686 	Mono_Set_Cursor (32,1);
   1687 	Mono_Printf ("%d",index);
   1688 
   1689 	Mono_Set_Cursor (32,2);
   1690 	if (index == -1) {
   1691 		Mono_Printf ("%d  ", GlobalChannel->Queue->Avg_Response_Time());
   1692 	} else {
   1693 		Mono_Printf ("%d  ", Connection[index]->Queue->Avg_Response_Time());
   1694 	}
   1695 
   1696 	Mono_Set_Cursor (59,1);
   1697 	Mono_Printf ("%d  ", SendOverflows);
   1698 
   1699 	Mono_Set_Cursor (59,2);
   1700 	Mono_Printf ("%d  ", ReceiveOverflows);
   1701 
   1702 	for (i = 0; i < NumBufs; i++) {
   1703 		if (BufferFlags[i]) {
   1704 			txt[i] = 'X';
   1705 		} else {
   1706 			txt[i] = '_';
   1707 		}
   1708 	}
   1709 	txt[i] = 0;
   1710 	Mono_Set_Cursor ((80-NumBufs)/2,3);
   1711 	Mono_Printf ("%s",txt);
   1712 
   1713 #else
   1714 	index = index;
   1715 	refresh = refresh;
   1716 #endif
   1717 }	/* end of Mono_Debug_Print */
   1718 
   1719 
   1720 /***************************************************************************
   1721  * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory			*
   1722  *                                                                         *
   1723  * INPUT:                                                                  *
   1724  *		none.																						*
   1725  *                                                                         *
   1726  * OUTPUT:                                                                 *
   1727  *		1 = OK, 0 = error																		*
   1728  *                                                                         *
   1729  * WARNINGS:                                                               *
   1730  *		none.																						*
   1731  *                                                                         *
   1732  * HISTORY:                                                                *
   1733  *   12/20/1994 BR : Created.                                              *
   1734  *=========================================================================*/
   1735 int IPXManagerClass::Alloc_RealMode_Mem(void)
   1736 {
   1737 #ifdef NOT_FOR_WIN95
   1738 	union REGS regs;
   1739 	struct SREGS sregs;
   1740 	int size;									// required size of allocation
   1741 	unsigned char *realmode;				// start addresses of real-mode data
   1742 	int realmodelen;							// length of real-mode data
   1743 	unsigned long func_val;
   1744 	char *p;										// for parsing buffer
   1745 	int i;
   1746 
   1747 	/*------------------------------------------------------------------------
   1748 	Compute # of buffers we need to allocate, & the max size of each one
   1749 	------------------------------------------------------------------------*/
   1750 	NumBufs = Glb_NumPackets + (Pvt_NumPackets * CONNECT_MAX);
   1751 
   1752 	PacketLen = Glb_MaxPacketLen + sizeof (GlobalHeaderType);
   1753 	if (Pvt_MaxPacketLen + sizeof (CommHeaderType) > PacketLen)
   1754 		PacketLen = Pvt_MaxPacketLen + sizeof (CommHeaderType);
   1755 
   1756 	FullPacketLen = PacketLen + sizeof(IPXHeaderType);
   1757 
   1758 	/*------------------------------------------------------------------------
   1759 	Compute the size of everything we'll ever need, allocate it in one big
   1760 	chunk.  The memory is used as follows:
   1761 	- Real-mode assembly IPX callback routine, plus its data,
   1762 	  (which includes the ListenECB)
   1763 	- Array of IPX Packet buffers (IPXHeader plus data buffer)
   1764 	- SendECB: ECB for sending
   1765 	- SendHeader: IPX Header for sending
   1766 	- SendBuf: Packet buffer for sending
   1767 	- BufferFlags: 1 byte for each incoming packet buffer; 1=in use, 0=free
   1768 	------------------------------------------------------------------------*/
   1769 	realmode = (unsigned char *)Get_RM_IPX_Address();
   1770 	realmodelen = Get_RM_IPX_Size();
   1771 	size = realmodelen + 				// assembly routine & its data
   1772 		(FullPacketLen * NumBufs) +	// array of packet buffers
   1773 		sizeof(ECBType) +					// SendECB
   1774 		FullPacketLen +					// SendHeader & SendBuf
   1775 		NumBufs;								// BufferFlags
   1776 	if (size > 65535)
   1777 		return(false);
   1778 
   1779 	/*------------------------------------------------------------------------
   1780 	Allocate DOS memory for the ECB, IPXHeader & packet buffers:
   1781 	AX = 0x100
   1782 	BX = # paragraphs to allocate
   1783 	- if Success, AX = real-mode segment, DX = selector
   1784 	- if Failure, carry flag is set
   1785 	------------------------------------------------------------------------*/
   1786 	memset (&regs, 0 ,sizeof(regs));
   1787 	segread (&sregs);
   1788 	regs.x.eax = DPMI_ALLOC_DOS_MEM;						// DPMI function to call
   1789 	regs.x.ebx = ((size + 15) >> 4);						// # paragraphs to allocate
   1790 	int386x (DPMI_INT, &regs, &regs, &sregs);			// allocate the memory
   1791 	/*........................................................................
   1792 	If the carry flag is set, DPMI is indicating an error.
   1793 	........................................................................*/
   1794 	if (regs.x.cflag) {
   1795 		return(false);
   1796 	}
   1797 
   1798 	/*........................................................................
   1799 	Save the values of the returned segment & selector
   1800 	........................................................................*/
   1801 	Selector = regs.w.dx;
   1802 	Segment = regs.w.ax;
   1803 	RealMemSize = size;
   1804 	RealModeData = (RealModeDataType *)(((long)Segment) << 4);
   1805 
   1806 	/*------------------------------------------------------------------------
   1807 	Lock the memory (since we're servicing interrupts with it)
   1808 	AX = 0x600
   1809 	BX:CX = starting linear address of memory to lock
   1810 	SI:DI = size of region to lock (in bytes)
   1811 	- If Failure, carry flag is set.
   1812 	------------------------------------------------------------------------*/
   1813 	memset (&regs, 0 ,sizeof(regs));
   1814 	segread (&sregs);
   1815 	regs.x.eax = DPMI_LOCK_MEM;							// DPMI function to call
   1816 	regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;
   1817 	regs.x.ecx = ((long)RealModeData & 0x0000ffff);
   1818 	regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;
   1819 	regs.x.edi = ((long)RealMemSize & 0x0000ffff);
   1820 	int386x (DPMI_INT, &regs, &regs, &sregs);			// call DPMI
   1821 	/*........................................................................
   1822 	If the carry flag is set, DPMI is indicating an error.
   1823 	........................................................................*/
   1824 	if (regs.x.cflag) {
   1825 		memset (&regs, 0 ,sizeof(regs));
   1826 		segread (&sregs);
   1827 		regs.x.eax = DPMI_FREE_DOS_MEM;						// DPMI function to call
   1828 		regs.x.edx = Selector;									// ptr to free
   1829 		int386x (DPMI_INT, &regs, &regs, &sregs);			// free the memory
   1830 		return(false);
   1831 	}
   1832 
   1833 	/*------------------------------------------------------------------------
   1834 	Copy the Real-mode code into our memory buffer
   1835 	------------------------------------------------------------------------*/
   1836 	p = (char *)(((long)Segment) << 4);
   1837 	memcpy (p,realmode,realmodelen);
   1838 	p += realmodelen;
   1839 
   1840 	/*------------------------------------------------------------------------
   1841 	Compute & save the entry point for the real-mode packet handler
   1842 	------------------------------------------------------------------------*/
   1843 	func_val = (unsigned long)RealModeData;
   1844 	Handler = (((func_val & 0xffff0) << 12) |
   1845 		((func_val & 0x000f) + RealModeData->FuncOffset));
   1846 
   1847 	/*------------------------------------------------------------------------
   1848 	Fill in buffer pointers
   1849 	------------------------------------------------------------------------*/
   1850 	ListenECB = &(RealModeData->ListenECB);
   1851 
   1852 	FirstHeaderBuf = (IPXHeaderType *)p;
   1853 	FirstDataBuf = (((char *)FirstHeaderBuf) + sizeof(IPXHeaderType));
   1854 	CurIndex = 0;
   1855 	CurHeaderBuf = FirstHeaderBuf;
   1856 	CurDataBuf = FirstDataBuf;
   1857 	p += FullPacketLen * NumBufs;
   1858 
   1859 	SendECB = (ECBType *)p;
   1860 	p += sizeof (ECBType);
   1861 
   1862 	SendHeader = (IPXHeaderType *)p;
   1863 	p += sizeof (IPXHeaderType);
   1864 
   1865 	SendBuf = (char *)p;
   1866 	p += PacketLen;
   1867 
   1868 	BufferFlags = (char *)p;
   1869 
   1870 	/*------------------------------------------------------------------------
   1871 	Fill in the real-mode routine's data (The ECB will be filled in when we
   1872 	command IPX to Listen).
   1873 	------------------------------------------------------------------------*/
   1874 	RealModeData->NumBufs = (short)NumBufs;
   1875 	RealModeData->BufferFlags = (char *)
   1876 		((((long)BufferFlags & 0xffff0) << 12) |
   1877 		((long)BufferFlags & 0x0000f));
   1878 	RealModeData->PacketSize = (short)FullPacketLen;
   1879 	RealModeData->FirstPacketBuf = (IPXHeaderType *)
   1880 		((((long)FirstHeaderBuf & 0xffff0) << 12) |
   1881 		((long)FirstHeaderBuf & 0x0000f));
   1882 	RealModeData->CurIndex = 0;
   1883 	RealModeData->CurPacketBuf = RealModeData->FirstPacketBuf;
   1884 	RealModeData->Semaphore = 0;
   1885 	RealModeData->ReEntrantCount = 0;
   1886 
   1887 	/*------------------------------------------------------------------------
   1888 	Init state of all buffers to empty
   1889 	------------------------------------------------------------------------*/
   1890 	for (i = 0; i < NumBufs; i++)
   1891 		BufferFlags[i] = 0;
   1892 
   1893 	/*------------------------------------------------------------------------
   1894 	Check the start & end markers in the real-mode memory area
   1895 	------------------------------------------------------------------------*/
   1896 	if (RealModeData->Marker1 != 0x1111 ||
   1897 		RealModeData->Marker2 != 0x2222) {
   1898 		Free_RealMode_Mem();
   1899 		return(false);
   1900 	} else {
   1901 		return(true);
   1902 	}
   1903 #else	//NOT_FOR_WIN95
   1904 
   1905 	return (TRUE);
   1906 
   1907 #endif	//NOT_FOR_WIN95
   1908 }
   1909 
   1910 
   1911 /***************************************************************************
   1912  * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory				*
   1913  *                                                                         *
   1914  * INPUT:                                                                  *
   1915  *		none.																						*
   1916  *                                                                         *
   1917  * OUTPUT:                                                                 *
   1918  *		1 = OK, 0 = error																		*
   1919  *                                                                         *
   1920  * WARNINGS:                                                               *
   1921  *		none.																						*
   1922  *                                                                         *
   1923  * HISTORY:                                                                *
   1924  *   12/20/1994 BR : Created.                                              *
   1925  *=========================================================================*/
   1926 int IPXManagerClass::Free_RealMode_Mem(void)
   1927 {
   1928 #ifdef NOT_FOR_WIN95
   1929 	union REGS regs;
   1930 	struct SREGS sregs;
   1931 	int rc = 1;
   1932 
   1933 	/*------------------------------------------------------------------------
   1934 	Unlock the memory
   1935 	------------------------------------------------------------------------*/
   1936 	memset (&regs, 0 ,sizeof(regs));
   1937 	segread (&sregs);
   1938 	regs.x.eax = DPMI_UNLOCK_MEM;							// DPMI function to call
   1939 	regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;
   1940 	regs.x.ecx = ((long)RealModeData & 0x0000ffff);
   1941 	regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;
   1942 	regs.x.edi = ((long)RealMemSize & 0x0000ffff);
   1943 	int386x (DPMI_INT, &regs, &regs, &sregs);			// call DPMI
   1944 	/*........................................................................
   1945 	If the carry flag is set, DPMI is indicating an error.
   1946 	........................................................................*/
   1947 	if (regs.x.cflag) {
   1948 		rc = 0;
   1949 	}
   1950 
   1951 	/*------------------------------------------------------------------------
   1952 	Free DOS memory
   1953 	------------------------------------------------------------------------*/
   1954 	memset (&regs, 0 ,sizeof(regs));
   1955 	segread (&sregs);
   1956 	regs.x.eax = DPMI_FREE_DOS_MEM;						// DPMI function to call
   1957 	regs.x.edx = Selector;									// ptr to free
   1958 	int386x (DPMI_INT, &regs, &regs, &sregs);			// free the memory
   1959 
   1960 	return(rc);
   1961 
   1962 #else	// NOT_FOR_WIN95
   1963 
   1964 	return (1);
   1965 
   1966 #endif	// NOT_FOR_WIN95
   1967 }	/* end of Free_RealMode_Mem */
   1968 
   1969